refactor: 调整滚动条样式,删除OverlayScrollbar组件及其样式

This commit is contained in:
2025-09-15 21:35:36 +08:00
parent 16d8eae61f
commit e5896d05b1
4 changed files with 7 additions and 145 deletions

View File

@ -19,6 +19,7 @@ import { Sheet, SheetContent, SheetTitle, SheetTrigger } from "@/components/ui/s
import { Menu } from "lucide-react"
import { ThemeModeToggle } from "../common/theme-toggle"
import { AvatarWithDropdownMenu } from "./avatar-with-dropdown-menu"
import { cn } from "@/lib/utils"
const navbarMenuComponents = [
{
@ -70,18 +71,18 @@ function NavMenuCenter() {
{navbarMenuComponents.map((item) => (
<NavigationMenuItem key={item.title}>
{item.href ? (
<NavigationMenuLink asChild className={navigationMenuTriggerStyle()}>
<NavigationMenuLink asChild className={cn(navigationMenuTriggerStyle(), "bg-transparent")}>
<Link href={item.href} className="flex items-center gap-1 font-extrabold">
<span>{item.title}</span>
</Link>
</NavigationMenuLink>
) : item.children ? (
<>
<NavigationMenuTrigger className="flex items-center gap-1 font-extrabold">
<NavigationMenuTrigger className="flex items-center gap-1 font-extrabold bg-transparent">
<span>{item.title}</span>
</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="grid gap-2 p-0 min-w-[200px] max-w-[600px] grid-cols-[repeat(auto-fit,minmax(120px,1fr))]">
<ul className="grid gap-2 p-0 min-w-[200px] max-w-[600px] grid-cols-[repeat(auto-fit,minmax(120px,1fr))] ">
{item.children.map((child) => (
<ListItem
key={child.title}

View File

@ -1,104 +0,0 @@
import React, { useEffect, useRef, useState } from "react";
import styles from "./overlay-scrollbar.module.css";
export default function OverlayScrollbar({
children,
className,
style,
}: {
children: React.ReactNode;
className?: string;
style?: React.CSSProperties;
}) {
const scrollRef = useRef<HTMLDivElement | null>(null);
const thumbRef = useRef<HTMLDivElement | null>(null);
const [thumbHeight, setThumbHeight] = useState(0);
const [thumbTop, setThumbTop] = useState(0);
const dragging = useRef(false);
const startY = useRef(0);
const startScrollTop = useRef(0);
useEffect(() => {
const el = scrollRef.current;
if (!el) return;
const update = () => {
const visible = el.clientHeight;
const total = el.scrollHeight;
const ratio = visible / Math.max(total, 1);
const h = Math.max(ratio * visible, 24);
const top = total > visible ? (el.scrollTop / (total - visible)) * (visible - h) : 0;
setThumbHeight(h);
setThumbTop(isFinite(top) ? top : 0);
if (thumbRef.current) {
const percent = total > visible ? Math.round((el.scrollTop / (total - visible)) * 100) : 0;
thumbRef.current.setAttribute("aria-valuenow", String(percent));
}
};
update();
el.addEventListener("scroll", update, { passive: true });
window.addEventListener("resize", update);
const obs = new MutationObserver(update);
obs.observe(el, { childList: true, subtree: true });
return () => {
el.removeEventListener("scroll", update);
window.removeEventListener("resize", update);
obs.disconnect();
};
}, []);
useEffect(() => {
const onMove = (e: MouseEvent) => {
if (!dragging.current || !scrollRef.current) return;
const el = scrollRef.current;
const visible = el.clientHeight;
const total = el.scrollHeight;
const h = thumbHeight;
const delta = e.clientY - startY.current;
const proportion = delta / Math.max(visible - h, 1);
el.scrollTop = Math.min(Math.max(startScrollTop.current + proportion * (total - visible), 0), total - visible);
};
const onUp = () => {
dragging.current = false;
document.body.style.userSelect = "";
};
window.addEventListener("mousemove", onMove);
window.addEventListener("mouseup", onUp);
return () => {
window.removeEventListener("mousemove", onMove);
window.removeEventListener("mouseup", onUp);
};
}, [thumbHeight]);
const onThumbMouseDown = (e: React.MouseEvent) => {
dragging.current = true;
startY.current = e.clientY;
if (scrollRef.current) startScrollTop.current = scrollRef.current.scrollTop;
document.body.style.userSelect = "none";
};
return (
<div className={`${styles.container} ${className || ""}`} style={{ position: "relative", ...style }}>
<div ref={scrollRef} className={styles.content} tabIndex={0}>
{children}
</div>
<div className={styles.track} aria-hidden={false}>
<div
ref={thumbRef}
role="scrollbar"
aria-orientation="vertical"
aria-valuemin={0}
aria-valuemax={100}
className={styles.thumb}
style={{ height: thumbHeight, transform: `translateY(${thumbTop}px)` }}
onMouseDown={onThumbMouseDown}
/>
</div>
</div>
);
}

View File

@ -1,35 +0,0 @@
.container {
position: relative;
}
.content {
overflow: auto;
max-height: 100%;
/* hide native scrollbars but keep scrolling */
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
.content::-webkit-scrollbar {
display: none; /* Chrome/Safari */
}
.track {
pointer-events: none; /* track itself not interactive */
position: absolute;
right: 8px;
top: 0;
bottom: 0;
width: 12px;
display: flex;
align-items: flex-start;
justify-content: center;
}
.thumb {
pointer-events: auto; /* thumb is interactive */
width: 8px;
margin-top: 4px;
background: rgba(0, 0, 0, 0.32);
border-radius: 9999px;
transition: background 0.12s ease;
}
.thumb:hover {
background: rgba(0, 0, 0, 0.6);
}