feat: start of scroller

This commit is contained in:
TrèsAbhi committed 2026-02-01 12:24:55 -06:00
1 parent 015d457d23
commit ddb869e767
4 files changed
+100 -5

No files matched your search

@@ -0,0 +1,42 @@
.scroller {
display: flex;
flex-direction: column;
.content {
overflow: auto;
scrollbar-width: none;
&::-webkit-scrollbar {
display: none;
width: 0;
height: 0;
}
}
.bar-wrapper {
padding: var(--space-1);
background-color: blue;
.bar-container {
background-color: red;
height: 10px;
position: relative;
.bar {
height: 100%;
min-width: min(100%, var(--space-6));
position: absolute;
background-color: green;
cursor: grab;
&:active {
cursor: grabbing;
}
}
}
}
}
@@ -0,0 +1,55 @@
import { useEffect, useRef, type ComponentProps } from "react";
import { classNames } from "../../core/ui/classNames";
import styles from "./index.module.css";
interface ScrollerProps extends ComponentProps<"div"> {}
export function Scroller({ children, className, ...props }: ScrollerProps) {
const bar = useRef<HTMLDivElement>(null!);
const container = useRef<HTMLDivElement>(null!);
const content = useRef<HTMLDivElement>(null!);
useEffect(() => {
function updateSize() {
bar.current.style.width = `${(content.current.clientWidth / content.current.scrollWidth) * 100}%`;
}
let lastX = 0;
function handlePointerDown(event: PointerEvent) {
lastX = event.clientX;
window.addEventListener("pointermove", handlePointerMove);
window.addEventListener("pointerup", handlePointerUp);
}
function handlePointerMove(event: PointerEvent) {
const dx = event.clientX - lastX;
lastX = event.clientX;
}
function handlePointerUp() {
window.removeEventListener("pointermove", handlePointerMove);
window.removeEventListener("pointerup", handlePointerUp);
}
updateSize();
bar.current.addEventListener("pointerdown", handlePointerDown);
return () => {
bar.current.removeEventListener("pointerdown", handlePointerDown);
};
}, []);
return (
<div className={classNames(styles.scroller, className)} {...props}>
<div className={styles.content} ref={content}>
{children}
</div>
<div className={styles["bar-wrapper"]}>
<div className={styles["bar-container"]} ref={container}>
<div className={styles.bar} ref={bar} />
</div>
</div>
</div>
);
}