feat(frontend): replace native scrollbar styling with OverlayScrollbars

Adopt OverlayScrollbars for cross-platform consistent overlay scrollbars
with auto-hide on pointer leave, hover grow effect, and click-to-scroll.

- Add overlayscrollbars + overlayscrollbars-react dependencies
- Rewrite ScrollArea component from Radix to OverlayScrollbars wrapper
- Define custom theme `os-theme-codeg` in globals.css (6px → 8px on hover)
- Initialize body-level overlay scrollbar via OverlayScrollbarsInit
- Migrate all scrollbar-thin / scrollbar-thin-edge usages to ScrollArea
- Keep native .scrollbar-thin fallback for virtua scroll containers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
xintaofei
2026-04-12 20:16:46 +08:00
parent ad50cc28fc
commit 0fafe782ee
13 changed files with 411 additions and 336 deletions

View File

@@ -28,6 +28,7 @@ import { STATUS_ORDER, STATUS_COLORS } from "@/lib/types"
import { SidebarConversationCard } from "./sidebar-conversation-card"
import { Button } from "@/components/ui/button"
import { Skeleton } from "@/components/ui/skeleton"
import { ScrollArea } from "@/components/ui/scroll-area"
import {
ContextMenu,
ContextMenuTrigger,
@@ -205,8 +206,6 @@ export function SidebarConversationList({
cancelled: false,
})
const scrollContainerRef = useRef<HTMLDivElement>(null)
const scrollToActiveRef = useRef<() => void>(() => {})
const pendingScrollRef = useRef(false)
const virtualizerRef = useRef<VirtualizerHandle>(null)
@@ -479,12 +478,8 @@ export function SidebarConversationList({
) : (
<ContextMenu>
<ContextMenuTrigger asChild>
<div
ref={scrollContainerRef}
className={cn(
"flex-1 min-h-0 overflow-y-auto scrollbar-thin px-2",
"[overflow-anchor:none]"
)}
<ScrollArea
className={cn("flex-1 min-h-0 px-2", "[overflow-anchor:none]")}
>
<Virtualizer ref={virtualizerRef} itemSize={CARD_HEIGHT}>
{flatItems.map((item) => {
@@ -537,7 +532,7 @@ export function SidebarConversationList({
)
})}
</Virtualizer>
</div>
</ScrollArea>
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuItem onSelect={handleNewConversation}>