Skip to content

ScrollArea (components/ui/scroll-area.tsx)

Overview

A customizable scroll area component built with Radix UI that provides cross-browser styled scrollbars with support for both vertical and horizontal scrolling.

Features

  • Custom scrollbars
  • Horizontal scrolling
  • Vertical scrolling
  • Thumb dragging
  • Smooth scrolling
  • Responsive design
  • Accessibility support
  • ARIA attributes
  • Touch support
  • Custom styling

Dependencies

import * as React from 'react'
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area'
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils'

Props

interface ScrollAreaProps extends React.HTMLAttributes<HTMLDivElement> {
  orientation?: 'vertical' | 'horizontal' | 'both';
  type?: 'auto' | 'always' | 'scroll' | 'hover';
  scrollHideDelay?: number;
  className?: string;
}

interface ScrollBarProps extends ScrollAreaPrimitive.ScrollAreaScrollbarProps {
  orientation?: 'vertical' | 'horizontal';
  className?: string;
}

Implementation

State Management

const [isScrolling, setIsScrolling] = useState(false);
const [scrollPos, setScrollPos] = useState({ x: 0, y: 0 });

useEffect(() => {
  if (type === 'hover') {
    const timer = setTimeout(() => {
      setIsScrolling(false);
    }, scrollHideDelay);
    return () => clearTimeout(timer);
  }
}, [isScrolling, type, scrollHideDelay]);

Methods

const handleScroll = (event: React.UIEvent<HTMLDivElement>) => {
  const target = event.currentTarget;
  setScrollPos({
    x: target.scrollLeft,
    y: target.scrollTop
  });
  setIsScrolling(true);
};

const handleScrollEnd = () => {
  if (type === 'hover') {
    setIsScrolling(false);
  }
};

Unique Functionality

  • Custom scrollbar rendering
  • Scroll position tracking
  • Visibility control
  • Touch interaction
  • Orientation handling
  • ARIA attributes

HTML Structure

<ScrollAreaPrimitive.Root
  type={type}
  className={cn("relative overflow-hidden", className)}
  {...props}
>
  <ScrollAreaPrimitive.Viewport
    className="h-full w-full rounded-[inherit]"
    onScroll={handleScroll}
  >
    {children}
  </ScrollAreaPrimitive.Viewport>
  <ScrollBar
    orientation="vertical"
    className={cn(
      "flex touch-none select-none transition-colors",
      orientation !== 'horizontal' && "h-full w-2.5 border-l border-l-transparent p-[1px]",
      type === 'hover' && !isScrolling && "opacity-0"
    )}
  />
  <ScrollBar
    orientation="horizontal"
    className={cn(
      "flex touch-none select-none transition-colors",
      orientation !== 'vertical' && "h-2.5 border-t border-t-transparent p-[1px]",
      type === 'hover' && !isScrolling && "opacity-0"
    )}
  />
  <ScrollAreaPrimitive.Corner className="bg-border" />
</ScrollAreaPrimitive.Root>

<ScrollAreaPrimitive.ScrollAreaScrollbar
  orientation={orientation}
  className={cn(
    "flex touch-none select-none transition-colors",
    orientation === 'vertical' && "h-full w-2.5 border-l border-l-transparent p-[1px]",
    orientation === 'horizontal' && "h-2.5 border-t border-t-transparent p-[1px]",
    className
  )}
  {...props}
>
  <ScrollAreaPrimitive.ScrollAreaThumb 
    className={cn(
      "relative rounded-full bg-border",
      orientation === 'vertical' && "flex-1",
      orientation === 'horizontal' && "flex-1"
    )}
  />
</ScrollAreaPrimitive.ScrollAreaScrollbar>

API Integration

No direct API integration.

Components Used

Exports the following components: - ScrollArea - ScrollBar - ScrollAreaViewport - ScrollAreaScrollbar - ScrollAreaThumb - ScrollAreaCorner

Notes

  • Built on Radix UI primitives
  • Handles both scroll directions
  • Manages scrollbar visibility
  • Provides smooth scrolling
  • Maintains accessibility features
  • Supports custom styling
  • Uses semantic HTML elements

Pages/Components Referenced By