Languages
[Edit]
EN

React - simple animated expander example

9 points
Created by:
a_horse
478

In this short article we would like to show how to create simple exander component in React.

Simple expander component in React.
Simple expander component in React.

Simple solution (multiple active items example)

// ONLINE-RUNNER:browser;

//Note: Uncomment import lines during working with JSX Compiler.
// import React from 'react';
// import ReactDOM from 'react-dom';

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

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 silver',
    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 >
  );
};

const root = document.querySelector('#root');
ReactDOM.render(<App/>, root );

 

Alternative solution (only one active item example)

In this section expander items use common context to do not let expand more than one item in xsame time.

// ONLINE-RUNNER:browser;

//Note: Uncomment import lines during working with JSX Compiler.
// import React from 'react';
// import ReactDOM from 'react-dom';

const expanderStyle = {
    padding: '0 2px',
    border: '1px solid silver'
};

const itemStyle = {
    margin: '2px 0',
    padding: '2px',
    border: '1px solid silver'
};

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 silver',
    height: 'auto',
    filter: 'opacity(1)'
};

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

const ExpanderContext = React.createContext();

const Expander = ({children}) => {
    const [expandedItem, setExpandedItem] = React.useState(null);
    const expander = {
      	isExpandedItem: (title) => title === expandedItem,
      	setExpandedItem: (title) => {
    		setExpandedItem(expandedItem === title ? null : title);
        }
    };
  	return (
      <ExpanderContext.Provider value={expander}>
        <div style={expanderStyle}>
          {children}
        </div>
      </ExpanderContext.Provider>
    );
};

const Item = ({title, children}) => {
  	const expander = React.useContext(ExpanderContext);
  	const expanded = expander.isExpandedItem(title);
  	const handleHeaderClick = () => {
    	expander.setExpandedItem(title);
    };
  	return (
      <div style={itemStyle}>
        <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={{width: '500px', height: '250px'}}>
      <Expander>
        <Item title="🍏🍌🍊 Fruits">
          <ul>
            <li>🍏 Apple</li>
            <li>🍌 Banana</li>
            <li>🍊 Orange</li>
          </ul>
        </Item>
        <Item title="🥕🥒🍅 Vegetables">
          <ul>
            <li>🥕 Carrot</li>
            <li>🥒 Cucumber</li>
            <li>🍅 Tomato</li>
          </ul>
        </Item>
      </Expander>
    </div >
  );
};

const root = document.querySelector('#root');
ReactDOM.render(<App/>, root );

 

See also

  1. React - create simple animated expander

Donate to Dirask
Our content is created by volunteers - like Wikipedia. If you think, the things we do are good, donate us. Thanks!
Join to our subscribers to be up to date with content, news and offers.

ReactJS

React - simple animated expander
Native Advertising
🚀
Get your tech brand or product in front of software developers.
For more information Contact us
Dirask - we help you to
solve coding problems.
Ask question.

❤️💻 🙂

Join