

<Preview name="BasicScrollAreaExample" />

## Overview [#overview]

The **ScrollArea** component provides a scrollable container with customizable scrollbars that match your design system. Built on Base UI primitives, it supports vertical, horizontal, and bidirectional scrolling with optional scroll shadow indicators that show users when more content is available.

## Usage [#usage]

```tsx
import { ScrollArea, ScrollAreaContent } from "@tilt-legal/cubitt-components/primitives";
```

```tsx
<ScrollArea className="h-72 w-48 rounded-md border">
  <ScrollAreaContent className="p-4">
    {/* Scrollable content */}
  </ScrollAreaContent>
</ScrollArea>
```

## Examples [#examples]

### Horizontal Scroll [#horizontal-scroll]

Scroll horizontally through content by setting `orientation="horizontal"`.

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="HorizontalScrollAreaExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import { ScrollArea, ScrollAreaContent } from "@tilt-legal/cubitt-components/primitives";

    export default function Component() {
      const artworks = [
        { artist: "Ornella Binni", art: "Reflected (2019)" },
        { artist: "Tom Byrom", art: "Mountain Mist (2020)" },
        // ...more items
      ];

      return (
        <ScrollArea
          className="w-96 whitespace-nowrap rounded-md border"
          orientation="horizontal"
        >
          <ScrollAreaContent className="flex w-max space-x-4 p-4">
            {artworks.map((artwork) => (
              <figure key={artwork.artist} className="shrink-0">
                <div className="overflow-hidden rounded-md">
                  <div className="h-36 w-48 bg-gradient-to-br from-muted to-muted-foreground/20" />
                </div>
                <figcaption className="pt-2 text-muted-foreground text-xs">
                  Photo by{" "}
                  <span className="font-semibold text-foreground">
                    {artwork.artist}
                  </span>
                </figcaption>
              </figure>
            ))}
          </ScrollAreaContent>
        </ScrollArea>
      );
    }
    ```
  </Tab>
</Tabs>

### Both Directions [#both-directions]

Enable scrolling in both directions with `orientation="both"`.

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="BothScrollAreaExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import { ScrollArea, ScrollAreaContent } from "@tilt-legal/cubitt-components/primitives";

    export default function Component() {
      return (
        <ScrollArea className="h-72 w-96 rounded-md border" orientation="both">
          <ScrollAreaContent className="p-4">
            <div className="w-[600px]">
              <h4 className="mb-4 font-medium text-sm leading-none">
                Wide Content with Many Items
              </h4>
              <div className="space-y-4">
                {Array.from({ length: 20 }).map((_, i) => (
                  <div key={i} className="flex gap-4">
                    <div className="h-12 w-48 shrink-0 rounded bg-muted" />
                    <div className="h-12 w-48 shrink-0 rounded bg-muted" />
                    <div className="h-12 w-48 shrink-0 rounded bg-muted" />
                  </div>
                ))}
              </div>
            </div>
          </ScrollAreaContent>
        </ScrollArea>
      );
    }
    ```
  </Tab>
</Tabs>

### Vertical Scroll Shadow [#vertical-scroll-shadow]

Add scroll shadow indicators to show users there's more content to scroll. The shadow fades in/out based on scroll position.

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="VerticalShadowScrollAreaExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import { ScrollArea, ScrollAreaContent, Separator } from "@tilt-legal/cubitt-components/primitives";

    export default function Component() {
      const tags = Array.from({ length: 50 }).map(
        (_, i, a) => `v1.2.0-beta.${a.length - i}`
      );

      return (
        <ScrollArea className="h-72 w-48 rounded-md border" scrollShadow="vertical">
          <ScrollAreaContent className="p-4">
            <h4 className="mb-4 font-medium text-sm leading-none">Tags</h4>
            {tags.map((tag) => (
              <div key={tag}>
                <div className="text-sm">{tag}</div>
                <Separator className="my-2" />
              </div>
            ))}
          </ScrollAreaContent>
        </ScrollArea>
      );
    }
    ```
  </Tab>
</Tabs>

### Horizontal Scroll Shadow [#horizontal-scroll-shadow]

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="HorizontalShadowScrollAreaExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import { ScrollArea, ScrollAreaContent } from "@tilt-legal/cubitt-components/primitives";

    export default function Component() {
      return (
        <ScrollArea
          className="w-96 whitespace-nowrap rounded-md border"
          orientation="horizontal"
          scrollShadow="horizontal"
        >
          <ScrollAreaContent className="flex w-max space-x-4 p-4">
            {/* Content items */}
          </ScrollAreaContent>
        </ScrollArea>
      );
    }
    ```
  </Tab>
</Tabs>

### Both Scroll Shadows [#both-scroll-shadows]

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="BothShadowScrollAreaExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import { ScrollArea, ScrollAreaContent } from "@tilt-legal/cubitt-components/primitives";

    export default function Component() {
      return (
        <ScrollArea
          className="h-72 w-96 rounded-md border"
          orientation="both"
          scrollShadow="both"
        >
          <ScrollAreaContent className="p-4">
            {/* Wide and tall content */}
          </ScrollAreaContent>
        </ScrollArea>
      );
    }
    ```
  </Tab>
</Tabs>

### Custom Shadow Configuration [#custom-shadow-configuration]

Fine-tune the scroll shadow appearance with custom size, gradient stop percentage, and opacity values.

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="CustomShadowScrollAreaExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import { ScrollArea, ScrollAreaContent, Separator } from "@tilt-legal/cubitt-components/primitives";

    export default function Component() {
      const tags = Array.from({ length: 50 }).map(
        (_, i, a) => `v1.2.0-beta.${a.length - i}`
      );

      return (
        <ScrollArea
          className="h-72 w-64 rounded-md border"
          scrollShadow={{
            vertical: { size: "80px", stopPercent: 60, stopOpacity: 90 },
          }}
        >
          <ScrollAreaContent className="p-4">
            <h4 className="mb-4 font-medium text-sm leading-none">
              Custom Shadow Configuration
            </h4>
            <p className="mb-4 text-muted-foreground text-xs">
              This scroll area has a larger shadow (80px) that stays solid for 60%
              of its height, then fades at 90% opacity before becoming transparent.
            </p>
            {tags.map((tag) => (
              <div key={tag}>
                <div className="text-sm">{tag}</div>
                <Separator className="my-2" />
              </div>
            ))}
          </ScrollAreaContent>
        </ScrollArea>
      );
    }
    ```
  </Tab>
</Tabs>

***

## API Reference [#api-reference]

### ScrollArea [#scrollarea]

The root scrollable container component.

| Prop           | Type                                                                                                           | Default      | Description                              |
| -------------- | -------------------------------------------------------------------------------------------------------------- | ------------ | ---------------------------------------- |
| `orientation`  | `"vertical"` \| `"horizontal"` \| `"both"`                                                                     | `"vertical"` | Direction of scrolling.                  |
| `scrollShadow` | `"vertical"` \| `"horizontal"` \| `"both"` \| `"none"` \| `ScrollShadowAxisConfig` \| `ScrollShadowSideConfig` | `"none"`     | Scroll shadow indicator configuration.   |
| `className`    | `string`                                                                                                       | -            | Additional CSS classes for the viewport. |

#### ScrollShadowConfig [#scrollshadowconfig]

The base configuration object for individual shadow settings:

| Property      | Type      | Default  | Description                                                                                 |
| ------------- | --------- | -------- | ------------------------------------------------------------------------------------------- |
| `size`        | `string`  | `"40px"` | Size of the shadow gradient (e.g., `"40px"`, `"100px"`).                                    |
| `stopPercent` | `number`  | `0`      | Percentage (0-100) where the solid color ends and fading begins.                            |
| `stopOpacity` | `number`  | `100`    | Opacity (0-100) of the starting color before fading to transparent.                         |
| `snap`        | `boolean` | `false`  | When true, shadow appears at full size immediately instead of growing with scroll progress. |

#### ScrollShadowObjectConfig [#scrollshadowobjectconfig]

The object configuration allows flexible shadow setup with type-safe constraints:

* **Vertical axis**: Use either `vertical` OR `top`/`bottom` (not both)
* **Horizontal axis**: Use either `horizontal` OR `left`/`right` (not both)
* **Cross-axis mixing**: You CAN mix `vertical` with `left`/`right` (different axes)

| Property     | Type                              | Description                                      |
| ------------ | --------------------------------- | ------------------------------------------------ |
| `vertical`   | `boolean` \| `ScrollShadowConfig` | Shortcut for top and bottom shadows.             |
| `horizontal` | `boolean` \| `ScrollShadowConfig` | Shortcut for left and right shadows.             |
| `top`        | `boolean` \| `ScrollShadowConfig` | Top shadow (cannot be used with `vertical`).     |
| `bottom`     | `boolean` \| `ScrollShadowConfig` | Bottom shadow (cannot be used with `vertical`).  |
| `left`       | `boolean` \| `ScrollShadowConfig` | Left shadow (cannot be used with `horizontal`).  |
| `right`      | `boolean` \| `ScrollShadowConfig` | Right shadow (cannot be used with `horizontal`). |

<Accordions type="single">
  <Accordion title="Configuration Examples">
    ```tsx
    // Axis shortcuts
    scrollShadow={{ vertical: true }}
    scrollShadow={{ vertical: { size: "60px" }, horizontal: true }}

    // Individual sides
    scrollShadow={{ top: true, bottom: false }}
    scrollShadow={{ left: { size: "40px" }, right: { size: "80px" } }}

    // Cross-axis mixing (allowed - different axes)
    scrollShadow={{ vertical: true, left: { size: "60px" } }}
    scrollShadow={{ top: true, horizontal: { size: "40px" } }}
    scrollShadow={{ top: { size: "80px" }, bottom: false, left: true, right: true }}
    ```
  </Accordion>

  <Accordion title="Type Safety">
    TypeScript enforces that you cannot mix axis shortcuts with their corresponding sides:

    ```tsx
    // ✅ Valid - cross-axis mixing
    scrollShadow={{ vertical: true, left: true }}
    scrollShadow={{ top: true, horizontal: true }}

    // ❌ Invalid - TypeScript error (same-axis conflict)
    scrollShadow={{ vertical: true, top: false }}      // Error!
    scrollShadow={{ horizontal: true, left: true }}    // Error!
    ```
  </Accordion>
</Accordions>

### ScrollAreaContent [#scrollareacontent]

Container for the scrollable content.

| Prop        | Type     | Default | Description                             |
| ----------- | -------- | ------- | --------------------------------------- |
| `className` | `string` | -       | Additional CSS classes for the content. |

### ScrollBar [#scrollbar]

Custom scrollbar component (used internally, but can be customized).

| Prop          | Type                           | Default      | Description                               |
| ------------- | ------------------------------ | ------------ | ----------------------------------------- |
| `orientation` | `"vertical"` \| `"horizontal"` | `"vertical"` | Direction of the scrollbar.               |
| `className`   | `string`                       | -            | Additional CSS classes for the scrollbar. |
