DEV Community

Cover image for React Collapsible Component with Auto Height Detection.
Alex Suarez
Alex Suarez

Posted on • Updated on

React Collapsible Component with Auto Height Detection.

Collapsible components with variable heights are hard, but not anymore, this example will make you rethink how you develop this in your company library from now on! Let's get into it!

Step 1: Create the Collapsible Component

For this example, I'm using styled-components but feel free to use plane css, or any css-in-js library you prefer

// Collapsible component 

interface Animation {
  duration?: number;
  ease?: string;
}

interface CollapsibleProps {
  children: React.ReactNode;
  open: boolean;
  animation?: Animation;
}

const defaultAnimationValues = {
  duration: 0.2,
  ease: "ease-in-out"
};

const CollapsibleWrapper = styled.div<{ open: boolean; animation: Animation }>`
  display: grid;
  grid-template-rows: ${(props) => (props.open ? "1fr" : "0fr")};
  opacity: 0;
  transition: all ${(props) => props.animation.duration}s
    ${(props) => props.animation.ease};
  opacity: ${(props) => (props.open ? 1 : 0)};
`;

const CollapsibleInner = styled.div`
  overflow: hidden;
`;

export const Collapsible: React.FC<CollapsibleProps> = ({
  children,
  open,
  animation = defaultAnimationValues
}) => {
  return (
    <CollapsibleWrapper open={open} animation={animation}>
      <CollapsibleInner>{children}</CollapsibleInner>
    </CollapsibleWrapper>
  );
};
Enter fullscreen mode Exit fullscreen mode

I added extra props to control animation timing and speed to make more customisable, beyond that there's not to much here here except for one detail...

grid-template-rows: ${(props) => (props.open ? "1fr" : "0fr")};
Enter fullscreen mode Exit fullscreen mode

This is the secret sauce! This line will actually open and close the Collapsible component adjusting the wrapper component height based on the children height!

Step2: Using the component

This is also incredible straightforward, set the state for toggling "show" and render whatever you want inside your new Collapsible component!

// App component 

export default function App() {
  const [show, setShow] = React.useState(false);
  return (
    <div className="App">
      <button onClick={() => setShow(!show)}>click</button>
      <Collapsible open={show}>
        <div className="bg-gray-100 py-4">
          <h1>Hello CodeSandbox</h1>
          <h2>Start editing to see some magic happen!</h2>
        </div>
      </Collapsible>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Magic gif

Now you can stop using those crazy height-controlled components! Wrap the code from the next codesanbox

Top comments (0)