react-collapsed
v4.1.2
Published
A React custom-hook for creating flexible and accessible expand/collapse components.
Downloads
300,231
Maintainers
Readme
🙈 react-collapsed (useCollapse)
A React hook for creating accessible expand/collapse components. Animates the height using CSS transitions from 0
to auto
.
Features
- Handles the height of animations of your elements,
auto
included! - You control the UI -
useCollapse
provides the necessary props, you control the styles and the elements. - Accessible out of the box - no need to worry if your collapse/expand component is accessible, since this takes care of it for you!
- No animation framework required! Simply powered by CSS animations
- Written in TypeScript
Demo
Installation
$ npm i react-collapsed
Usage
Simple Usage
import React from 'react'
import { useCollapse } from 'react-collapsed'
function Demo() {
const { getCollapseProps, getToggleProps, isExpanded } = useCollapse()
return (
<div>
<button {...getToggleProps()}>
{isExpanded ? 'Collapse' : 'Expand'}
</button>
<section {...getCollapseProps()}>Collapsed content 🙈</section>
</div>
)
}
Control it yourself
import React, { useState } from 'react'
import { useCollapse } from 'react-collapsed'
function Demo() {
const [isExpanded, setExpanded] = useState(false)
const { getCollapseProps, getToggleProps } = useCollapse({ isExpanded })
return (
<div>
<button
{...getToggleProps({
onClick: () => setExpanded((prevExpanded) => !prevExpanded),
})}
>
{isExpanded ? 'Collapse' : 'Expand'}
</button>
<section {...getCollapseProps()}>Collapsed content 🙈</section>
</div>
)
}
API
const { getCollapseProps, getToggleProps, isExpanded, setExpanded } =
useCollapse({
isExpanded: boolean,
defaultExpanded: boolean,
collapsedHeight: 0,
easing: string,
duration: number,
onTransitionStateChange: func,
})
useCollapse
Config
The following are optional properties passed into useCollapse({ })
:
| Prop | Type | Default | Description |
| ----------------------- | -------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| isExpanded | boolean | undefined
| If true, the Collapse is expanded |
| defaultExpanded | boolean | false
| If true, the Collapse will be expanded when mounted |
| collapsedHeight | number | 0
| The height of the content when collapsed |
| easing | string | cubic-bezier(0.4, 0, 0.2, 1)
| The transition timing function for the animation |
| duration | number | undefined
| The duration of the animation in milliseconds. By default, the duration is programmatically calculated based on the height of the collapsed element |
| onTransitionStateChange | function | no-op | Handler called with at each stage of the transition animation |
| hasDisabledAnimation | boolean | false | If true, will disable the animation |
| id | string | number | undefined
| Unique identifier used to for associating elements appropriately for accessibility. |
What you get
| Name | Description | | ---------------- | ----------------------------------------------------------------------------------------------------------- | | getCollapseProps | Function that returns a prop object, which should be spread onto the collapse element | | getToggleProps | Function that returns a prop object, which should be spread onto an element that toggles the collapse panel | | isExpanded | Whether or not the collapse is expanded (if not controlled) | | setExpanded | Sets the hook's internal isExpanded state |
Alternative Solutions
- react-spring - JavaScript animation based library that can potentially have smoother animations. Requires a bit more work to create an accessible collapse component.
- react-animate-height - Another library that uses CSS transitions to animate to any height. It provides components, not a hook.
FAQ
The collapse works by manipulating the height
property. If an element has vertical padding, that padding expandes the size of the element, even if it has height: 0; overflow: hidden
.
To avoid this, simply move that padding from the element to an element directly nested within in.
// from
<div {...getCollapseProps({style: {padding: 20}})}
This will do weird things
</div>
// to
<div {...getCollapseProps()}
<div style={{padding: 20}}>
Much better!
</div>
</div>