Native overflow with styled scrollbars. Use the default vertical direction or add horizontal scrolling for wide content.
tsx
import { Fragment } from "react"import { ScrollArea } from "@/components/ui/scroll-area"import { Separator } from "@/components/ui/separator"const tags = Array.from({ length: 50 }).map( (_, i, a) => `v1.2.0-beta.${a.length - i}`,)export function Example() { return ( <ScrollArea className="h-72 w-48 rounded-md border border-border"> <div className="p-4"> <h4 className="mb-4 text-sm font-medium tracking-wide text-foreground"> Tags </h4> {tags.map((tag, i) => ( <Fragment key={tag}> <div className="text-sm font-normal tracking-wide text-foreground"> {tag} </div> {i < tags.length - 1 ? <Separator className="my-2" /> : null} </Fragment> ))} </div> </ScrollArea> )}Installation
npx @arctis-sh/@arctis-sh/ui@latest add scroll-areaUsage
import { ScrollArea } from "@/components/ui/scroll-area"<ScrollArea className="h-[200px] w-[350px] rounded-md border border-border"> <div className="p-4">Scrollable content.</div></ScrollArea>Composition
Vertical and horizontal scrollbars are included automatically.
ScrollArea ├── ScrollBar (vertical) └── ScrollBar (horizontal)
Basic
A fixed-height area with a long list. Put padding on the content rather than the root.
tsx
import { Fragment } from "react"import { ScrollArea } from "@/components/ui/scroll-area"import { Separator } from "@/components/ui/separator"const tags = Array.from({ length: 50 }).map( (_, i, a) => `v1.2.0-beta.${a.length - i}`,)export function Example() { return ( <ScrollArea className="h-72 w-48 rounded-md border border-border"> <div className="p-4"> <h4 className="mb-4 text-sm font-medium tracking-wide text-foreground"> Tags </h4> {tags.map((tag, i) => ( <Fragment key={tag}> <div className="text-sm font-normal tracking-wide text-foreground"> {tag} </div> {i < tags.length - 1 ? <Separator className="my-2" /> : null} </Fragment> ))} </div> </ScrollArea> )}Horizontal
Wide content reveals the horizontal scrollbar. Give the root a width and keep the row at w-max.
tsx
import { ScrollArea } from "@/components/ui/scroll-area"const works = [ { label: "Attachment 1", art: "/assets/brand/demos/attachments/attachment-1.png", }, { label: "Attachment 2", art: "/assets/brand/demos/attachments/attachment-2.png", }, { label: "Attachment 3", art: "/assets/brand/demos/attachments/attachment-3.png", }, { label: "Attachment 4", art: "/assets/brand/demos/attachments/attachment-4.png", }, { label: "Attachment 5", art: "/assets/brand/demos/attachments/attachment-5.png", },]export function Example() { return ( <ScrollArea className="w-96 whitespace-nowrap rounded-md border border-border"> <div className="flex w-max gap-4 p-4"> {works.map((work) => ( <figure key={work.label} className="shrink-0"> <div className="overflow-hidden rounded-md"> <img src={work.art} alt={work.label} className="aspect-[3/4] h-fit w-[150px] object-cover" /> </div> <figcaption className="pt-2 text-xs font-normal tracking-wide text-muted-foreground"> {work.label} </figcaption> </figure> ))} </div> </ScrollArea> )}API Reference
ScrollArea
The sized root contains the scroll viewport. Vertical and horizontal scrollbars appear only when content overflows.
| Prop | Type | Default |
|---|---|---|
| className | string | — |
<ScrollArea className="h-48 w-64"> <div className="p-4">Long content…</div></ScrollArea>ScrollBar
Rendered by ScrollArea when needed. Exported for the composition API.
| Prop | Type | Default |
|---|---|---|
| orientation | "vertical" | "horizontal" | "vertical" |
| className | string | — |
<ScrollBar orientation="vertical" />



