useCollapse manages vertical expand/collapse transitions and returns transition-aware props to spread onto the collapsible element.
Usage
import { useCollapse } from '@kuzenbo/hooks';
import { useState } from 'react';
function Demo() {
const [expanded, setExpanded] = useState(false);
const { getCollapseProps } = useCollapse({ expanded });
return (
<div>
<button onClick={() => setExpanded((e) => !e)}>
{expanded ? 'Collapse' : 'Expand'}
</button>
<div {...getCollapseProps()}>
<div style={{ padding: 20 }}>
<p>This content will smoothly expand and collapse</p>
<p>The height is automatically calculated</p>
</div>
</div>
</div>
);
}
API Reference
Parameters
Collapse configuration object.
Whether the content should be expanded.
Transition duration in milliseconds. When omitted, duration is calculated from content height.
input.transitionTimingFunction
CSS timing function for the transition.
Callback fired when the height transition finishes.
Callback fired when a transition starts.
When true, collapsed content stays mounted and is hidden with styles.
Returns
state
'entering' | 'entered' | 'exiting' | 'exited'
Current transition state.
getCollapseProps
(input?: GetCollapsePropsInput) => GetCollapsePropsReturnValue
Function that returns props to spread onto the collapsible element.
Accordion
import { useCollapse } from '@kuzenbo/hooks';
import { useState } from 'react';
function Accordion() {
const [openItem, setOpenItem] = useState<number | null>(null);
const items = [
{ title: 'Section 1', content: 'Content for section 1' },
{ title: 'Section 2', content: 'Content for section 2' },
{ title: 'Section 3', content: 'Content for section 3' },
];
return (
<div>
{items.map((item, index) => (
<AccordionItem
key={index}
title={item.title}
content={item.content}
expanded={openItem === index}
onToggle={() => setOpenItem(openItem === index ? null : index)}
/>
))}
</div>
);
}
function AccordionItem({ title, content, expanded, onToggle }) {
const { getCollapseProps } = useCollapse({ expanded });
return (
<div>
<button onClick={onToggle}>{title}</button>
<div {...getCollapseProps()}>
<div style={{ padding: 16 }}>{content}</div>
</div>
</div>
);
}
Custom Duration
import { useCollapse } from '@kuzenbo/hooks';
import { useState } from 'react';
function Demo() {
const [expanded, setExpanded] = useState(false);
const { getCollapseProps } = useCollapse({
expanded,
transitionDuration: 1000,
transitionTimingFunction: 'ease-in-out',
});
return (
<div>
<button onClick={() => setExpanded(!expanded)}>Toggle</button>
<div {...getCollapseProps()}>
<div style={{ padding: 20 }}>Slow transition content</div>
</div>
</div>
);
}
Keep Mounted
import { useCollapse } from '@kuzenbo/hooks';
import { useState } from 'react';
function Demo() {
const [expanded, setExpanded] = useState(false);
const { getCollapseProps, state } = useCollapse({
expanded,
keepMounted: true, // Content stays in DOM when collapsed
});
return (
<div>
<button onClick={() => setExpanded(!expanded)}>Toggle</button>
<p>State: {state}</p>
<div {...getCollapseProps()}>
<div style={{ padding: 20 }}>This content stays mounted</div>
</div>
</div>
);
}
With Callbacks
import { useCollapse } from '@kuzenbo/hooks';
import { useState } from 'react';
function Demo() {
const [expanded, setExpanded] = useState(false);
const { getCollapseProps } = useCollapse({
expanded,
onTransitionStart: () => console.log('Transition started'),
onTransitionEnd: () => console.log('Transition ended'),
});
return (
<div>
<button onClick={() => setExpanded(!expanded)}>Toggle</button>
<div {...getCollapseProps()}>
<div style={{ padding: 20 }}>Content with callbacks</div>
</div>
</div>
);
}
Custom Styles
import { useCollapse } from '@kuzenbo/hooks';
import { useState } from 'react';
function Demo() {
const [expanded, setExpanded] = useState(false);
const { getCollapseProps } = useCollapse({ expanded });
return (
<div>
<button onClick={() => setExpanded(!expanded)}>Toggle</button>
<div
{...getCollapseProps({
style: {
border: '1px solid #ccc',
borderRadius: 4,
},
})}
>
<div style={{ padding: 20 }}>Styled collapse content</div>
</div>
</div>
);
}