Skip to content

Instantly share code, notes, and snippets.

@manzyuk
Created June 13, 2025 16:46
Show Gist options
  • Save manzyuk/f6ba0f74a8de58c1f947adb4b4ae50cc to your computer and use it in GitHub Desktop.
Save manzyuk/f6ba0f74a8de58c1f947adb4b4ae50cc to your computer and use it in GitHub Desktop.
<html>
<body style="margin: 0">
<div id="root"></div>
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/[email protected]/babel.js"></script>
<script src="https://unpkg.com/@babel/[email protected]/babel.js"></script>
<script type="text/babel">
const items = [
{ id: 1, label: "Item 1", details: "Details for item 1" },
{ id: 2, label: "Item 2", details: "Details for item 2" },
{ id: 3, label: "Item 3", details: "Details for item 3" },
];
function SlidingPanelList() {
const [selected, setSelected] = React.useState(null);
const [panelVisible, setPanelVisible] = React.useState(false);
const [nextState, setNextState] = React.useState({
nextSelected: null,
nextPanelVisible: false,
});
const panelRef = React.useRef();
const handleTransformTransitionEnd = (e) => {
if (e.propertyName !== "transform") {
return;
}
const { nextSelected, nextPanelVisible } = nextState;
setSelected(nextSelected);
setPanelVisible(nextPanelVisible);
};
React.useEffect(() => {
if (panelRef.current) {
panelRef.current.addEventListener(
"transitionend",
handleTransformTransitionEnd
);
}
return () => {
if (panelRef.current) {
panelRef.current.removeEventListener(
"transitionend",
handleTransformTransitionEnd
);
}
};
});
const handleClick = (id) => {
if (selected === id) {
setPanelVisible(false);
setNextState({ nextSelected: null, nextPanelVisible: false });
} else if (selected !== null) {
setPanelVisible(false);
setNextState({ nextSelected: id, nextPanelVisible: true });
} else {
setPanelVisible(true);
setNextState({ nextSelected: id, nextPanelVisible: true });
}
};
const panelItem = items.find((item) => item.id === selected);
return (
<div style={{ display: "flex", height: 400 }}>
<ul
style={{
width: "100%",
borderRight: "1px solid #ccc",
margin: 0,
padding: 0,
listStyle: "none",
}}
>
{items.map((item) => (
<li
key={item.id}
style={{
padding: 16,
cursor: "pointer",
background: selected === item.id ? "#f0f0f0" : undefined,
}}
onClick={() => handleClick(item.id)}
>
{item.label}
</li>
))}
</ul>
<div
style={{
width: "20%",
position: "relative",
overflow: "visible",
}}
>
<div
ref={panelRef}
style={{
position: "absolute",
top: 0,
right: 0,
width: "100%",
height: "100%",
background: "#fff",
boxShadow: "-2px 0 8px rgba(0,0,0,0.1)",
transform: panelVisible
? "translateX(0)"
: "translateX(100%)",
transition: "transform 0.3s cubic-bezier(.4,0,.2,1)",
pointerEvents: panelVisible ? "auto" : "none",
// opacity: panelVisible ? 1 : 0,
}}
>
{panelItem && (
<div style={{ padding: 24 }}>
<h3>{panelItem.label}</h3>
<p>{panelItem.details}</p>
</div>
)}
</div>
</div>
</div>
);
}
ReactDOM.render(<SlidingPanelList />, document.getElementById("root"));
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment