Home

Scroll area

A box that scrolls its content behind a thin scrollbar and fades the edge that has more to show.

ui.scroll-areacomponents/ui/scroll-area.tsx

Use case

For the AI

Use it for any list that can outgrow its box: the invoices in a side panel, a client's notes, a long list inside a popover you build yourself. Give it a height and it fades at the top or the bottom only where more is hidden, which is the library's scroll rule. A table that scrolls sideways does not need it: its own container already fades.

Use it when

  • A list with a fixed height that may grow long
  • A panel's body that scrolls under a fixed header
  • Any region that would otherwise need overflow-y-auto

Use something else when

  • A table wider than its box: Table
  • The app's navigation rail: Sidebar
  • Options to pick from in a list that opens: Select
  • A few sections that can fold instead of scroll: Accordion

Examples

Code

Import

import { ScrollArea } from "@/components/ui/scroll-area"

Usage

type Invoice = { id: string; number: string; amount: string }

export function InvoiceList({ invoices }: { invoices: Invoice[] }) {
  return (
    <ScrollArea className="h-56 w-full max-w-xs rounded-[20px] bg-background shadow-(--shadow-rest)">
      <ul className="grid p-2">
        {invoices.map((invoice) => (
          <li key={invoice.id} className="flex h-9 items-center justify-between rounded-[10px] px-3 text-[13px] hover:bg-surface">
            <span>{invoice.number}</span>
            <span className="text-ink-4 tabular-nums">{invoice.amount}</span>
          </li>
        ))}
      </ul>
    </ScrollArea>
  )
}

Rules

  • Give it a bounded height (h-56, or a flex child with min-h-0); without one nothing scrolls.
  • Leave scrollFade on, its default: nothing that scrolls may cut a row in half at a hard edge.
  • Never a bare overflow-y-auto: use ScrollArea, or put scroll-fade (or scroll-fade-x) on the element that overflows.
  • The frame (corner, ground, shadow) goes on ScrollArea's className: the fade is on the inner viewport, so the frame never fades.
  • overscrollContain keeps a scroll inside it from scrolling the page behind; scrollbarGutter keeps the content clear of the scrollbar.