---
title: Scroll Area
description: A scrollable container with custom styled scrollbars, providing a consistent cross-browser experience.
---

<ComponentPreview name="scroll-area-demo" />

## Installation

<Tabs defaultValue="cli">

<TabsList>
  <TabsTrigger value="cli">CLI</TabsTrigger>
  <TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">

```bash
npx lightswind@latest add scroll-area
```

</TabsContent>

<TabsContent value="manual">

<Steps>

<Step>Copy and paste the following code into your project.</Step>

```tsx

import * as React from "react";
import { cn } from "@/components/lib/utils";

interface ScrollAreaProps extends React.HTMLAttributes<HTMLDivElement> {
  /** Reference to the viewport element */
  viewportRef?: React.RefObject<HTMLDivElement>;
  /** Maximum height of the scroll area */
  maxHeight?: string | number;
  /** Whether to show scrollbars */
  showScrollbars?: boolean;
  /** Whether to allow scrolling */
  scrollable?: boolean;
  /** The orientation of the scroll area */
  orientation?: "vertical" | "horizontal" | "both";
  /** Whether to smooth scroll */
  smooth?: boolean;
  /** Theme for the scrollbar */
  theme?: "default" | "minimal" | "none";
}

const ScrollArea = React.forwardRef<HTMLDivElement, ScrollAreaProps>(
  ({
    className,
    children,
    viewportRef,
    maxHeight,
    showScrollbars = true,
    scrollable = true,
    orientation = "vertical",
    smooth = false,
    theme = "default",
    ...props
  }, ref) => {
    const internalRef = React.useRef<HTMLDivElement>(null);
    const resolvedRef = viewportRef || internalRef;

    const style: React.CSSProperties = {
      maxHeight: maxHeight !== undefined ? (typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight) : undefined,
      ...props.style
    };

    // Orientation scroll classes
    const orientationClasses = {
      vertical: "overflow-y-auto overflow-x-hidden",
      horizontal: "overflow-x-auto overflow-y-hidden",
      both: "overflow-auto"
    };

    // Theme classes
    const themeClasses = {
      default: "themed-scrollbar",
      minimal: "minimal-scrollbar",
      none: "scrollbar-none"
    };

    return (
      <div
        ref={ref}
        className={cn("relative overflow-hidden", className)}
        style={style}
        {...props}
      >
        <div
          ref={resolvedRef}
          className={cn(
            "h-full w-full rounded-[inherit]",
            scrollable ? orientationClasses[orientation] : "overflow-hidden",
            smooth && "scroll-smooth",
            showScrollbars ? themeClasses[theme] : "scrollbar-none"
          )}
          data-lenis-prevent
        >
          {children}
        </div>
      </div>
    );
  }
);
ScrollArea.displayName = "ScrollArea";

interface ScrollBarProps extends React.HTMLAttributes<HTMLDivElement> {
  /** The orientation of the scrollbar */
  orientation?: "vertical" | "horizontal";
  /** Size of the scrollbar */
  size?: "thin" | "default" | "thick";
  /** Whether the scrollbar is visible */
  visible?: boolean;
}

const ScrollBar = React.forwardRef<HTMLDivElement, ScrollBarProps>(
  ({
    className,
    orientation = "vertical",
    size = "default",
    visible = false,
    ...props
  }, ref) => {
    // Size classes
    const sizeClasses = {
      thin: orientation === "vertical" ? "w-1" : "h-1",
      default: orientation === "vertical" ? "w-1.5" : "h-1.5",
      thick: orientation === "vertical" ? "w-2" : "h-2"
    };

    return (
      <div
        ref={ref}
        className={cn(
          "flex touch-none select-none transition-all",
          orientation === "vertical"
            ? `h-full ${sizeClasses[size]} border-l border-l-transparent p-[1px]`
            : `${sizeClasses[size]} flex-col border-t border-t-transparent p-[1px]`,
          visible ? "opacity-100" : "opacity-0 hover:opacity-100",
          className
        )}
        {...props}
      >
        <div className="relative flex-1 rounded-full bg-primary/50 hover:bg-primary transition-all duration-150" />
      </div>
    );
  }
);
ScrollBar.displayName = "ScrollBar";

export { ScrollArea, ScrollBar };

```

</Steps>

</TabsContent>

</Tabs>

## Usage

```tsx
import { ScrollArea, ScrollBar } from '@/components/lightswind/scroll-area';
```

```tsx
import { ScrollArea } from '@/components/lightswind/scroll-area';

export function ScrollAreaDemo() {
  return (
    <ScrollArea className="h-[200px] w-[350px] rounded-md border p-4">
      <div className="space-y-4">
        <h4 className="text-sm font-medium leading-none">Scrollable Content</h4>
        <p className="text-sm">
          This is a scrollable area with custom scrollbars. The content will scroll when it exceeds the height.
        </p>
        {/* Add more content here to make it scroll */}
        {Array.from({ length: 15 }).map((_, i) => (
          <div key={i} className="py-1">
            Row {i + 1}
          </div>
        ))}
      </div>
    </ScrollArea>
  );
}
```
