Radix Adaptive Scroll Area
lina/lina-radixFreeComponent
A responsive scroll area that feels native on touch devices, offering custom styling and enhanced interactions where it matters most.
Install it
npx shadcn@latest add https://lina.sameer.sh/r/lina-radix.jsonSource
1"use client";23import * as React from "react";45import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";67import { cn } from "@/lib/utils";89import { useTouchPrimary } from "@/hooks/use-has-primary-touch";1011const ScrollAreaContext = React.createContext<boolean>(false);12type Mask = {13 top: boolean;14 bottom: boolean;15 left: boolean;16 right: boolean;17};1819const ScrollArea = React.forwardRef<20 React.ComponentRef<typeof ScrollAreaPrimitive.Root>,21 React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root> & {22 viewportClassName?: string;23 /**24 * `maskHeight` is the height of the mask in pixels.25 * pass `0` to disable the mask26 * @default 3027 */28 maskHeight?: number;29 maskClassName?: string;30 }31>(({ className, children, scrollHideDelay = 0, viewportClassName, maskClassName, maskHeight = 30, ...props }, ref) => {32 const [showMask, setShowMask] = React.useState<Mask>({33 top: false,34 bottom: false,35 left: false,36 right: false,37 });38 const viewportRef = React.useRef<HTMLDivElement>(null);39 const isTouch = useTouchPrimary();4041 const checkScrollability = React.useCallback(() => {42 const element = viewportRef.current;43 if (!element) return;4445 const { scrollTop, scrollLeft, scrollWidth, clientWidth, scrollHeight, clientHeight } = element;46 setShowMask((prev) => ({47 ...prev,48 top: scrollTop > 0,49 bottom: scrollTop + clientHeight < scrollHeight - 1,50 left: scrollLeft > 0,51 right: scrollLeft + clientWidth < scrollWidth - 1,52 }));53 }, []);5455 React.useEffect(() => {56 if (typeof window === "undefined") return;5758 const element = viewportRef.current;59 if (!element) return;6061 const controller = new AbortController();62 const { signal } = controller;6364 const resizeObserver = new ResizeObserver(checkScrollability);65 resizeObserver.observe(element);6667 element.addEventListener("scroll", checkScrollability, { signal });68 window.addEventListener("resize", checkScrollability, { signal });6970 // Run an initial check whenever dependencies change (including pointer mode)71 checkScrollability();7273 return () => {74 controller.abort();75 resizeObserver.disconnect();76 };77 }, [checkScrollability, isTouch]);7879 return (80 <ScrollAreaContext.Provider value={isTouch}>81 {isTouch ? (82 <div83 ref={ref}84 role="group"85// … truncated
What it pulls in
npm packages
Files it writes
More from lina
All 10 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Command based on Lina's Base UI variantcommand-base | lina | Components | Free | 2 deps | |
| Command based on Lina's Radix UI variantcommand-radix | lina | Components | Free | 2 deps | |
| Horizontal Scroll Area Base Demohorizontal-scroll-demo-base | lina | Components | Free | no deps | |
| Horizontal Scroll Area Radix Demohorizontal-scroll-demo-radix | lina | Components | Free | no deps | |
| Base UI Adaptive Scroll Arealina-base | lina | Components | Free | 1 dep · 2 files | |
| Timezone Select Base UI Demotimezone-select-demo-base | lina | Components | Free | 1 dep | |
| Timezone Select Radix Demotimezone-select-demo-radix | lina | Components | Free | 1 dep | |
| Vertical Scroll Area Base Demovertical-scroll-demo-base | lina | Components | Free | no deps |
