Skip to content
40 linesCodeBlameRaw
1import { ScrollArea as Primitive } from "radix-ui";
2import type { ComponentProps } from "react";
3
4import { cn } from "../../lib/cn";
5
6// shadcn/ui's scroll area, styled with g1t's tokens: a box that scrolls
7// with a thin bar of its own, the same on every platform, for a list in a
8// panel or a sidebar. Plain `overflow-y-auto` with `[scrollbar-width:thin]`
9// does for most of the site; this is for where the bar must sit inside
10// rounded corners or stay out of the way until hovered.
11
12export function ScrollArea({ className, children, ...props }: ComponentProps<typeof Primitive.Root>) {
13 return (
14 <Primitive.Root data-slot="scroll-area" className={cn("relative overflow-hidden", className)} {...props}>
15 <Primitive.Viewport data-slot="scroll-area-viewport" className="size-full rounded-[inherit] outline-none focus-visible:ring-2 focus-visible:ring-accent">
16 {children}
17 </Primitive.Viewport>
18 <ScrollBar />
19 <Primitive.Corner />
20 </Primitive.Root>
21 );
22}
23
24export function ScrollBar({ className, orientation = "vertical", ...props }: ComponentProps<typeof Primitive.Scrollbar>) {
25 return (
26 <Primitive.Scrollbar
27 data-slot="scroll-area-scrollbar"
28 orientation={orientation}
29 className={cn(
30 "flex touch-none p-px transition-colors select-none",
31 orientation === "vertical" && "h-full w-2 border-l border-l-transparent",
32 orientation === "horizontal" && "h-2 flex-col border-t border-t-transparent",
33 className,
34 )}
35 {...props}
36 >
37 <Primitive.Thumb data-slot="scroll-area-thumb" className="relative flex-1 rounded-full bg-line-strong" />
38 </Primitive.Scrollbar>
39 );
40}