Skip to main content

Collapse

The Collapse component provides smooth expand and collapse animations for showing and hiding content. It’s commonly used for nested menus, expandable sections, and progressive disclosure patterns.

Installation

npm install @naturacosmeticos/natds-web

Usage

import { Collapse, Button } from '@naturacosmeticos/natds-web';
import { useState } from 'react';

function BasicCollapse() {
  const [open, setOpen] = useState(false);

  return (
    <div>
      <Button onClick={() => setOpen(!open)}>
        {open ? 'Hide' : 'Show'} Content
      </Button>
      <Collapse in={open}>
        <div>
          This content will smoothly expand and collapse
        </div>
      </Collapse>
    </div>
  );
}

Collapse Variants

Basic Collapse

Simple show/hide behavior:
function SimpleCollapse() {
  const [checked, setChecked] = useState(false);

  return (
    <div>
      <Button onClick={() => setChecked(!checked)}>
        Toggle Content
      </Button>
      <Collapse in={checked}>
        <div style={{ padding: 16 }}>
          Collapsed content appears here
        </div>
      </Collapse>
    </div>
  );
}

With Nested List

Use Collapse with List components:
import { Collapse, List, ListItem, ListItemText } from '@naturacosmeticos/natds-web';

function CollapsibleList() {
  const [open, setOpen] = useState(true);

  return (
    <List>
      <ListItem button onClick={() => setOpen(!open)}>
        <ListItemText primary="Inbox" />
      </ListItem>
      <Collapse in={open} timeout="auto" unmountOnExit>
        <List disablePadding>
          <ListItem>
            <ListItemText primary="Starred" />
          </ListItem>
          <ListItem>
            <ListItemText primary="Drafts" />
          </ListItem>
        </List>
      </Collapse>
    </List>
  );
}

Auto Duration

Automatically calculate transition time based on height:
<Collapse in={open} timeout="auto">
  <div>
    Content with automatic transition duration based on content height
  </div>
</Collapse>

Custom Duration

Specify custom enter and exit durations:
<Collapse 
  in={open} 
  timeout={{ enter: 500, exit: 300 }}
>
  <div>
    Content with custom transition timing
  </div>
</Collapse>

Unmount On Exit

Remove content from DOM when collapsed:
<Collapse in={open} unmountOnExit>
  <div>
    This content is removed from DOM when collapsed
  </div>
</Collapse>

Custom Collapsed Height

Set a minimum height when collapsed:
<Collapse 
  in={open} 
  collapsedHeight="40px"
>
  <div style={{ height: 200 }}>
    When collapsed, this maintains a 40px height
  </div>
</Collapse>

Multiple Sections

Manage multiple collapsible sections:
function MultipleCollapse() {
  const [openSections, setOpenSections] = useState({});

  const toggleSection = (section) => {
    setOpenSections(prev => ({
      ...prev,
      [section]: !prev[section]
    }));
  };

  return (
    <div>
      <Button onClick={() => toggleSection('section1')}>
        Section 1
      </Button>
      <Collapse in={openSections.section1}>
        <div>Content for section 1</div>
      </Collapse>

      <Button onClick={() => toggleSection('section2')}>
        Section 2
      </Button>
      <Collapse in={openSections.section2}>
        <div>Content for section 2</div>
      </Collapse>

      <Button onClick={() => toggleSection('section3')}>
        Section 3
      </Button>
      <Collapse in={openSections.section3}>
        <div>Content for section 3</div>
      </Collapse>
    </div>
  );
}

With Card

Collapsible card content:
import { Card, CardContent, CardActions, Button } from '@naturacosmeticos/natds-web';

function CollapsibleCard() {
  const [expanded, setExpanded] = useState(false);

  return (
    <Card>
      <CardContent>
        <Typography variant="h5">Card Title</Typography>
        <Typography variant="body2">
          Preview text that's always visible
        </Typography>
      </CardContent>
      <CardActions>
        <Button onClick={() => setExpanded(!expanded)}>
          {expanded ? 'Show Less' : 'Show More'}
        </Button>
      </CardActions>
      <Collapse in={expanded} timeout="auto" unmountOnExit>
        <CardContent>
          <Typography paragraph>
            Additional content that can be expanded and collapsed.
            This could include more details, specifications, or any other information.
          </Typography>
        </CardContent>
      </Collapse>
    </Card>
  );
}

Nested Collapse

function NestedCollapse() {
  const [level1, setLevel1] = useState(false);
  const [level2, setLevel2] = useState(false);

  return (
    <div>
      <Button onClick={() => setLevel1(!level1)}>
        Level 1
      </Button>
      <Collapse in={level1}>
        <div style={{ paddingLeft: 20 }}>
          <p>Level 1 content</p>
          <Button onClick={() => setLevel2(!level2)}>
            Level 2
          </Button>
          <Collapse in={level2}>
            <div style={{ paddingLeft: 20 }}>
              <p>Level 2 content</p>
            </div>
          </Collapse>
        </div>
      </Collapse>
    </div>
  );
}

Props

children
node
The content to be collapsed or expanded.
in
boolean
If true, the component will transition in and display the content.
timeout
number | { enter?: number, exit?: number } | 'auto'
The duration for the transition in milliseconds. You may specify a single timeout for all transitions, or individually with an object. Set to 'auto' to automatically calculate transition time based on height. Defaults to duration.standard.
collapsedHeight
string | number
default:"'0px'"
The height of the container when collapsed.
component
element
default:"'div'"
The component used for the root node. Either a string to use a DOM element or a component.
unmountOnExit
boolean
If true, the component will unmount when collapsed, removing it from the DOM.
onEnter
function
Callback fired before the component enters.
onEntering
function
Callback fired when the component is entering.
onEntered
function
Callback fired when the component has entered.
onExit
function
Callback fired before the component exits.
onExiting
function
Callback fired when the component is exiting.
onExited
function
Callback fired when the component has exited.

Best Practices

  • Use timeout="auto" for variable-height content
  • Add unmountOnExit to remove content from DOM when not visible
  • Provide clear visual indicators (buttons, icons) for toggle interaction
  • Consider using collapsedHeight instead of complete hiding for preview content
  • Avoid deeply nested collapses as they can be confusing
  • Use consistent animation timing across your application

Performance Tips

  • Use unmountOnExit for heavy content to improve performance
  • Consider lazy loading content that’s initially hidden
  • Avoid animating large DOM trees
  • Use CSS transforms when possible for smoother animations

Accessibility

  • Ensure toggle buttons have clear labels
  • Use ARIA attributes to indicate expanded/collapsed state
  • Make sure collapsed content is not focusable when hidden
  • Provide keyboard navigation support
  • Consider using aria-expanded on trigger elements

Common Patterns

FAQ Section

const faqs = [
  { question: 'What is this?', answer: 'Answer 1' },
  { question: 'How does it work?', answer: 'Answer 2' },
];

function FAQ() {
  const [openIndex, setOpenIndex] = useState(null);

  return (
    <div>
      {faqs.map((faq, index) => (
        <div key={index}>
          <Button onClick={() => setOpenIndex(openIndex === index ? null : index)}>
            {faq.question}
          </Button>
          <Collapse in={openIndex === index}>
            <div>{faq.answer}</div>
          </Collapse>
        </div>
      ))}
    </div>
  );
}
  • ExpansionPanel - For structured expandable panels
  • Accordion - For grouped expandable sections
  • List - Often used with Collapse for nested navigation

Build docs developers (and LLMs) love