About Marasi Drive Table Mobile
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import { useEffect, useState } from "react";
|
||||
import useWindowSize from "../../hooks/useWindowSize";
|
||||
|
||||
interface CustomScrollBarProps {
|
||||
containerRef: React.RefObject<HTMLElement | null>;
|
||||
inlinePadding: number;
|
||||
trackStyle?: string;
|
||||
thumbStyle?: string;
|
||||
}
|
||||
|
||||
function CustomScrollBar({
|
||||
containerRef,
|
||||
inlinePadding,
|
||||
trackStyle = "",
|
||||
thumbStyle = "",
|
||||
}: CustomScrollBarProps) {
|
||||
const [scrollLeft, setScrollLeft] = useState<number>(0);
|
||||
const [totalWidth, setTotalWidth] = useState<number>(0);
|
||||
const [containerWidth, setContainerWidth] = useState<number>(0);
|
||||
const [thumbVisible, setThumbVisible] = useState<boolean>(false);
|
||||
const windowSize = useWindowSize();
|
||||
|
||||
function GetContainer(): HTMLElement {
|
||||
if (!containerRef.current) {
|
||||
throw new Error("Container reference is not valid");
|
||||
}
|
||||
return containerRef.current;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setTotalWidth(GetContainer().scrollWidth);
|
||||
setContainerWidth(GetContainer().clientWidth);
|
||||
}, [windowSize]);
|
||||
|
||||
useEffect(() => {
|
||||
const container = GetContainer();
|
||||
let hideThumbTimeout: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
function handleContainerScroll() {
|
||||
setScrollLeft(container.scrollLeft);
|
||||
|
||||
if (!thumbVisible) setThumbVisible(true);
|
||||
if (hideThumbTimeout) clearTimeout(hideThumbTimeout);
|
||||
|
||||
hideThumbTimeout = setTimeout(() => {
|
||||
setThumbVisible(false);
|
||||
}, 750);
|
||||
}
|
||||
|
||||
container.addEventListener("scroll", handleContainerScroll);
|
||||
return () => {
|
||||
container.removeEventListener("scroll", handleContainerScroll);
|
||||
};
|
||||
}, [containerRef]);
|
||||
|
||||
const scrollPercent =
|
||||
totalWidth > containerWidth
|
||||
? (scrollLeft / (totalWidth - containerWidth)) * 100
|
||||
: 0;
|
||||
const thumbPosition =
|
||||
(scrollPercent / 100) * (containerWidth - 20 - inlinePadding * 2); // 20px - ширина ползунка
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`relative h-1 w-full bg-transparent rounded-full ${trackStyle}`}
|
||||
>
|
||||
<div
|
||||
className={`absolute w-5 h-1 bg-[#E2E2DC] rounded-full transition-opacity duration-250 ease-out ${
|
||||
thumbVisible ? "opacity-100" : "opacity-0"
|
||||
} ${thumbStyle}`}
|
||||
style={{ transform: `translateX(${thumbPosition}px)` }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default CustomScrollBar;
|
||||
Reference in New Issue
Block a user