mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 10:47:04 +02:00
feat: scroll functionality
This commit is contained in:
1 parent
ddb869e767
commit
f84f846e76
2 files changed
+60
-7
No files matched your search
@@ -1,6 +1,7 @@
|
||||
.scroller {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-3);
|
||||
|
||||
.content {
|
||||
overflow: auto;
|
||||
@@ -15,11 +16,15 @@
|
||||
}
|
||||
|
||||
.bar-wrapper {
|
||||
opacity: 0;
|
||||
padding: var(--space-1);
|
||||
background-color: blue;
|
||||
background-color: var(--gray-3);
|
||||
|
||||
transition: opacity var(--duration-brief);
|
||||
|
||||
border-radius: var(--max-size);
|
||||
|
||||
.bar-container {
|
||||
background-color: red;
|
||||
height: 10px;
|
||||
|
||||
position: relative;
|
||||
@@ -29,7 +34,8 @@
|
||||
min-width: min(100%, var(--space-6));
|
||||
position: absolute;
|
||||
|
||||
background-color: green;
|
||||
border-radius: var(--max-size);
|
||||
background-color: var(--gray-7);
|
||||
|
||||
cursor: grab;
|
||||
|
||||
@@ -39,4 +45,11 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus-within {
|
||||
.bar-wrapper {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,32 +10,72 @@ export function Scroller({ children, className, ...props }: ScrollerProps) {
|
||||
const content = useRef<HTMLDivElement>(null!);
|
||||
|
||||
useEffect(() => {
|
||||
function updateSize() {
|
||||
bar.current.style.width = `${(content.current.clientWidth / content.current.scrollWidth) * 100}%`;
|
||||
function updateBarSize() {
|
||||
const visible = content.current.clientWidth;
|
||||
const total = content.current.scrollWidth;
|
||||
|
||||
if (total <= 0) return;
|
||||
|
||||
bar.current.style.width = `${(visible / total) * 100}%`;
|
||||
}
|
||||
|
||||
function syncBarToScroll() {
|
||||
const maxTravel = container.current.clientWidth - bar.current.clientWidth;
|
||||
const maxScroll =
|
||||
content.current.scrollWidth - content.current.clientWidth;
|
||||
|
||||
if (maxScroll <= 0 || maxTravel <= 0) {
|
||||
bar.current.style.left = "0";
|
||||
return;
|
||||
}
|
||||
|
||||
const ratio = content.current.scrollLeft / maxScroll;
|
||||
bar.current.style.left = `${ratio * maxTravel}px`;
|
||||
}
|
||||
|
||||
let lastX = 0;
|
||||
|
||||
function handlePointerDown(event: PointerEvent) {
|
||||
lastX = event.clientX;
|
||||
bar.current.setPointerCapture(event.pointerId);
|
||||
|
||||
window.addEventListener("pointermove", handlePointerMove);
|
||||
window.addEventListener("pointerup", handlePointerUp);
|
||||
}
|
||||
|
||||
function handlePointerMove(event: PointerEvent) {
|
||||
const dx = event.clientX - lastX;
|
||||
lastX = event.clientX;
|
||||
|
||||
const maxTravel = container.current.clientWidth - bar.current.clientWidth;
|
||||
if (maxTravel <= 0) return;
|
||||
|
||||
const maxScroll =
|
||||
content.current.scrollWidth - content.current.clientWidth;
|
||||
const delta = (dx / maxTravel) * maxScroll;
|
||||
|
||||
content.current.scrollLeft += delta;
|
||||
|
||||
syncBarToScroll();
|
||||
}
|
||||
function handlePointerUp() {
|
||||
|
||||
function handlePointerUp(event: PointerEvent) {
|
||||
bar.current.releasePointerCapture(event.pointerId);
|
||||
window.removeEventListener("pointermove", handlePointerMove);
|
||||
window.removeEventListener("pointerup", handlePointerUp);
|
||||
}
|
||||
|
||||
updateSize();
|
||||
updateBarSize();
|
||||
syncBarToScroll();
|
||||
|
||||
bar.current.addEventListener("pointerdown", handlePointerDown);
|
||||
content.current.addEventListener("scroll", syncBarToScroll);
|
||||
window.addEventListener("resize", updateBarSize);
|
||||
|
||||
return () => {
|
||||
bar.current.removeEventListener("pointerdown", handlePointerDown);
|
||||
content.current.removeEventListener("scroll", syncBarToScroll);
|
||||
window.removeEventListener("resize", updateBarSize);
|
||||
};
|
||||
}, []);
|
||||
|
||||
|
||||
Reference in new issue
Block a user