This is the solution I have gone for. I've created a container that uses ref and a few methods to handle mouse click and drag. I can then pass whatever I want to scroll horizontally into the component.
import React, { ReactNode, useRef } from "react";
interface ScrollingDivProps {
children: ReactNode;
}
const ScrollingDiv: React.FC<ScrollingDivProps> = ({ children }) => {
const scrollRef = useRef<HTMLDivElement | null>(null);
const handleMouseDown = (e: React.MouseEvent) => {
const scrollContainer = scrollRef.current as HTMLDivElement & {
isDown: boolean;
startX: number;
scrollLeft: number;
};
if (!scrollContainer) return;
scrollContainer.isDown = true;
scrollContainer.startX = e.pageX - scrollContainer.offsetLeft;
};
const handleMouseLeave = () => {
const scrollContainer = scrollRef.current as HTMLDivElement & {
isDown: boolean;
};
if (!scrollContainer) return;
scrollContainer.isDown = false;
};
const handleMouseUp = () => {
const scrollContainer = scrollRef.current as HTMLDivElement & {
isDown: boolean;
};
if (!scrollContainer) return;
scrollContainer.isDown = false;
};
const handleMouseMove = (e: React.MouseEvent) => {
const scrollContainer = scrollRef.current as HTMLDivElement & {
isDown: boolean;
startX: number;
scrollLeft: number;
};
if (!scrollContainer || !scrollContainer.isDown) return;
e.preventDefault();
const x = e.pageX - scrollContainer.offsetLeft;
const walk = (x - scrollContainer.startX) * 2; // scroll-fast
scrollContainer.scrollLeft = scrollContainer.scrollLeft - walk;
};
return (
<div
className="scroll-container"
ref={scrollRef}
onMouseDown={handleMouseDown}
onMouseLeave={handleMouseLeave}
onMouseUp={handleMouseUp}
onMouseMove={handleMouseMove}
>
{children}
</div>
);
};
export default ScrollingDiv;
and the css
/* header buttons css */
.scroll-container {
display: flex;
overflow-x: auto;
-webkit-overflow-scrolling: touch; /* Enables smooth scrolling on iOS */
}
/* Hide scrollbar for Chrome, Safari and Opera */
.scroll-container::-webkit-scrollbar {
display: none;
}
/* Hide scrollbar for IE, Edge and Firefox */
.scroll-container {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
Use it as follows:
import ScrollingDiv from "./ScrollingDiv";
return (
<ScrollingDiv>
<ChildComponent />
</ScrollingDiv>
);
Tested and works well....