mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 19:49:50 +02:00
feat: simplify scrollbar
This commit is contained in:
1 parent
33209a6d31
commit
2e208507c3
2 files changed
+5
-107
No files matched your search
@@ -8,43 +8,13 @@
|
|||||||
.content {
|
.content {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
|
||||||
scrollbar-width: none;
|
padding-bottom: var(--space-4);
|
||||||
|
|
||||||
&::-webkit-scrollbar {
|
transition: scrollbar-color var(--duration-brief);
|
||||||
display: none;
|
scrollbar-color: transparent transparent;
|
||||||
width: 0;
|
|
||||||
height: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.bar-wrapper {
|
&:hover {
|
||||||
opacity: 0;
|
scrollbar-color: var(--gray-7) var(--gray-3);
|
||||||
padding: var(--space-1);
|
|
||||||
background-color: var(--gray-3);
|
|
||||||
|
|
||||||
transition: opacity var(--duration-brief);
|
|
||||||
|
|
||||||
border-radius: var(--max-size);
|
|
||||||
|
|
||||||
.bar-container {
|
|
||||||
height: var(--space-3);
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.bar {
|
|
||||||
height: 100%;
|
|
||||||
min-width: min(100%, var(--space-6));
|
|
||||||
position: absolute;
|
|
||||||
|
|
||||||
border-radius: var(--max-size);
|
|
||||||
background-color: var(--gray-7);
|
|
||||||
|
|
||||||
cursor: grab;
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
cursor: grabbing;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,36 +6,11 @@ import styles from "./index.module.css";
|
|||||||
interface ScrollerProps extends ComponentProps<"div"> {}
|
interface ScrollerProps extends ComponentProps<"div"> {}
|
||||||
|
|
||||||
export function Scroller({ children, className, ...props }: ScrollerProps) {
|
export function Scroller({ children, className, ...props }: ScrollerProps) {
|
||||||
const bar = useRef<HTMLDivElement>(null!);
|
|
||||||
const container = useRef<HTMLDivElement>(null!);
|
|
||||||
const content = useRef<HTMLDivElement>(null!);
|
const content = useRef<HTMLDivElement>(null!);
|
||||||
const curtainLeft = useRef<HTMLDivElement>(null!);
|
const curtainLeft = useRef<HTMLDivElement>(null!);
|
||||||
const curtainRight = useRef<HTMLDivElement>(null!);
|
const curtainRight = useRef<HTMLDivElement>(null!);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function updateBarSize() {
|
|
||||||
const visible = content.current.clientWidth;
|
|
||||||
const total = content.current.scrollWidth;
|
|
||||||
|
|
||||||
if (total <= 0) return;
|
|
||||||
|
|
||||||
bar.current.style.width = `${(visible / total) * 100}%`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function syncBar() {
|
|
||||||
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`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function syncCurtains() {
|
function syncCurtains() {
|
||||||
const maxScroll =
|
const maxScroll =
|
||||||
content.current.scrollWidth - content.current.clientWidth;
|
content.current.scrollWidth - content.current.clientWidth;
|
||||||
@@ -61,61 +36,20 @@ export function Scroller({ children, className, ...props }: ScrollerProps) {
|
|||||||
curtainRight.current.style.opacity = `${rightOpacity}`;
|
curtainRight.current.style.opacity = `${rightOpacity}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
syncBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
function handlePointerUp(event: PointerEvent) {
|
|
||||||
bar.current.releasePointerCapture(event.pointerId);
|
|
||||||
window.removeEventListener("pointermove", handlePointerMove);
|
|
||||||
window.removeEventListener("pointerup", handlePointerUp);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleScroll() {
|
function handleScroll() {
|
||||||
syncBar();
|
|
||||||
syncCurtains();
|
syncCurtains();
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleResize() {
|
function handleResize() {
|
||||||
updateBarSize();
|
|
||||||
syncBar();
|
|
||||||
syncCurtains();
|
syncCurtains();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateBarSize();
|
|
||||||
syncBar();
|
|
||||||
syncCurtains();
|
syncCurtains();
|
||||||
|
|
||||||
bar.current.addEventListener("pointerdown", handlePointerDown);
|
|
||||||
content.current.addEventListener("scroll", syncBar);
|
|
||||||
window.addEventListener("resize", handleResize);
|
window.addEventListener("resize", handleResize);
|
||||||
content.current.addEventListener("scroll", handleScroll);
|
content.current.addEventListener("scroll", handleScroll);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
bar.current.removeEventListener("pointerdown", handlePointerDown);
|
|
||||||
content.current.removeEventListener("scroll", syncBar);
|
|
||||||
window.removeEventListener("resize", handleResize);
|
window.removeEventListener("resize", handleResize);
|
||||||
content.current.removeEventListener("scroll", handleScroll);
|
content.current.removeEventListener("scroll", handleScroll);
|
||||||
};
|
};
|
||||||
@@ -127,12 +61,6 @@ export function Scroller({ children, className, ...props }: ScrollerProps) {
|
|||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles["bar-wrapper"]}>
|
|
||||||
<div className={styles["bar-container"]} ref={container}>
|
|
||||||
<div className={styles.bar} ref={bar} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div ref={curtainLeft} data-side="left" className={styles.curtain} />
|
<div ref={curtainLeft} data-side="left" className={styles.curtain} />
|
||||||
<div ref={curtainRight} data-side="right" className={styles.curtain} />
|
<div ref={curtainRight} data-side="right" className={styles.curtain} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in new issue
Block a user