mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 10:47:04 +02:00
feat: start of scroller
This commit is contained in:
1 parent
015d457d23
commit
ddb869e767
4 files changed
+100
-5
No files matched your search
@@ -2,6 +2,7 @@
|
||||
import { api } from "../core/api/dynamic";
|
||||
import { tools } from "../core/tools/tools";
|
||||
import { Heading } from "./Heading";
|
||||
import { Scroller } from "./Scroller";
|
||||
import { Section } from "./Section";
|
||||
import { TankCard } from "./TankCard";
|
||||
import ToolCard from "./ToolCard.astro";
|
||||
@@ -35,8 +36,6 @@ const popular = [
|
||||
}
|
||||
|
||||
.tanks {
|
||||
/* overflow-x: scroll; */
|
||||
overflow-x: hidden;
|
||||
z-index: 1;
|
||||
|
||||
.content {
|
||||
@@ -50,11 +49,11 @@ const popular = [
|
||||
<Section>
|
||||
<Heading size="2" className="title">{strings.home.tanks}</Heading>
|
||||
|
||||
<div class="tanks">
|
||||
<Scroller client:load className="tanks">
|
||||
<div class="content">
|
||||
{popular.map((tank) => <TankCard {tank} />)}
|
||||
</div>
|
||||
</div>
|
||||
</Scroller>
|
||||
|
||||
<ToolCard gradient {locale} tool={tools.tanks} />
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export function Scroller() {}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user