useHorizontalCollapse manages horizontal expand/collapse transitions and returns transition-aware props to spread onto the collapsible element.
Usage
import { useHorizontalCollapse } from '@kuzenbo/hooks';
import { useState } from 'react';
function Demo() {
const [expanded, setExpanded] = useState(false);
const { getCollapseProps } = useHorizontalCollapse({ expanded });
return (
<div style={{ display: 'flex' }}>
<button onClick={() => setExpanded((e) => !e)}>
{expanded ? 'Collapse' : 'Expand'}
</button>
<div {...getCollapseProps()}>
<div style={{ padding: 20, whiteSpace: 'nowrap' }}>
<p>This content will smoothly expand and collapse horizontally</p>
<p>The width is automatically calculated</p>
</div>
</div>
</div>
);
}
API Reference
Parameters
input
UseHorizontalCollapseInput
required
Horizontal collapse configuration object.
Whether the content should be expanded.
Transition duration in milliseconds. When omitted, duration is calculated from content width.
input.transitionTimingFunction
CSS timing function for the transition.
Callback fired when the width 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?: GetHorizontalCollapsePropsInput) => GetHorizontalCollapsePropsReturnValue
Function that returns props to spread onto the collapsible element.
import { useHorizontalCollapse } from '@kuzenbo/hooks';
import { useState } from 'react';
function Sidebar() {
const [expanded, setExpanded] = useState(true);
const { getCollapseProps } = useHorizontalCollapse({ expanded });
return (
<div style={{ display: 'flex' }}>
<nav {...getCollapseProps()}>
<div style={{ width: 250, padding: 20 }}>
<h3>Navigation</h3>
<ul>
<li>Dashboard</li>
<li>Settings</li>
<li>Profile</li>
</ul>
</div>
</nav>
<button onClick={() => setExpanded(!expanded)}>
{expanded ? '◀' : '▶'}
</button>
<main style={{ flex: 1, padding: 20 }}>
<h1>Main Content</h1>
</main>
</div>
);
}
Custom Duration
import { useHorizontalCollapse } from '@kuzenbo/hooks';
import { useState } from 'react';
function Demo() {
const [expanded, setExpanded] = useState(false);
const { getCollapseProps } = useHorizontalCollapse({
expanded,
transitionDuration: 500,
transitionTimingFunction: 'cubic-bezier(0.4, 0, 0.2, 1)',
});
return (
<div style={{ display: 'flex' }}>
<button onClick={() => setExpanded(!expanded)}>Toggle</button>
<div {...getCollapseProps()}>
<div style={{ padding: 20, whiteSpace: 'nowrap' }}>
Custom timing content
</div>
</div>
</div>
);
}
import { useHorizontalCollapse } from '@kuzenbo/hooks';
import { useState } from 'react';
function ExpandableToolbar() {
const [expanded, setExpanded] = useState(false);
const { getCollapseProps, state } = useHorizontalCollapse({ expanded });
return (
<div style={{ display: 'flex', alignItems: 'center' }}>
<button onClick={() => setExpanded(!expanded)}>⚙️</button>
<div {...getCollapseProps()}>
<div style={{ display: 'flex', gap: 8, padding: '0 16px' }}>
<button>Cut</button>
<button>Copy</button>
<button>Paste</button>
<button>Undo</button>
</div>
</div>
</div>
);
}
Keep Mounted
import { useHorizontalCollapse } from '@kuzenbo/hooks';
import { useState } from 'react';
function Demo() {
const [expanded, setExpanded] = useState(false);
const { getCollapseProps } = useHorizontalCollapse({
expanded,
keepMounted: true, // Content stays in DOM when collapsed
});
return (
<div style={{ display: 'flex' }}>
<button onClick={() => setExpanded(!expanded)}>Toggle</button>
<div {...getCollapseProps()}>
<div style={{ padding: 20, whiteSpace: 'nowrap' }}>
This content stays mounted
</div>
</div>
</div>
);
}
With Callbacks
import { useHorizontalCollapse } from '@kuzenbo/hooks';
import { useState } from 'react';
function Demo() {
const [expanded, setExpanded] = useState(false);
const { getCollapseProps } = useHorizontalCollapse({
expanded,
onTransitionStart: () => console.log('Starting transition'),
onTransitionEnd: () => console.log('Transition complete'),
});
return (
<div style={{ display: 'flex' }}>
<button onClick={() => setExpanded(!expanded)}>Toggle</button>
<div {...getCollapseProps()}>
<div style={{ padding: 20 }}>Content with callbacks</div>
</div>
</div>
);
}
Responsive Panel
import { useHorizontalCollapse } from '@kuzenbo/hooks';
import { useState } from 'react';
function ResponsiveLayout() {
const [showSidebar, setShowSidebar] = useState(false);
const { getCollapseProps } = useHorizontalCollapse({
expanded: showSidebar,
transitionDuration: 300,
});
return (
<div style={{ display: 'flex', minHeight: '100vh' }}>
<aside {...getCollapseProps()}>
<div style={{ width: 300, padding: 20, background: '#f5f5f5' }}>
<h2>Sidebar</h2>
<nav>
<a href="#">Home</a>
<a href="#">About</a>
<a href="#">Contact</a>
</nav>
</div>
</aside>
<main style={{ flex: 1, padding: 20 }}>
<button onClick={() => setShowSidebar(!showSidebar)}>
{showSidebar ? 'Hide' : 'Show'} Sidebar
</button>
<h1>Main Content</h1>
</main>
</div>
);
}