- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Attachment
- Avatar
- Badge
- Breadcrumb
- Bubble
- Button
- Button Group
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Collapsible
- Combobox
- Command
- Context Menu
- Date Picker
- Dialog
- Drawer
- Dropdown Menu
- Empty
- Field
- Hover Card
- Input
- Input OTP
- Input Group
- Item
- Kbd
- Label
- Marker
- Menubar
- Message
- Message Scroller
- Native Select
- Navigation Menu
- Pagination
- Popover
- Progress
- Radio Group
- Resizable
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toggle
- Toggle Group
- Tooltip
- New Component
Tags
Component 1
Component 2
Component 3
Component 4
Component 5
Component 6
Component 7
Component 8
Component 9
Component 10
Component 11
Component 12
Component 13
Component 14
Component 15
Component 16
Component 17
Component 18
Component 19
Component 20
Component 21
Component 22
Component 23
Component 24
Component 25
Component 26
Component 27
Component 28
Component 29
Component 30
Component 31
Component 32
Component 33
Component 34
Component 35
Component 36
Component 37
Component 38
Component 39
Component 40
Component 41
Component 42
Component 43
Component 44
Component 45
Component 46
Component 47
Component 48
Component 49
Component 50
import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area";
import { Separator } from "@/components/ui/separator";
const tags = Array.from({ length: 50 }, (_, i) => `Component ${i + 1}`);
const artworks = [
{ artist: "Charlie Parker", title: "Ornithology" },
{ artist: "Miles Davis", title: "So What" },
{ artist: "Bill Evans", title: "Waltz for Debby" },
{ artist: "John Coltrane", title: "A Love Supreme" },
{ artist: "Dave Brubeck", title: "Take Five" },
{ artist: "Miles Davis", title: "Kind of Blue" },
{ artist: "John Coltrane", title: "Giant Steps" },
{ artist: "Herbie Hancock", title: "Maiden Voyage" },
];
export const ScrollAreaDemo = () => (
<div className="flex gap-6">
{/* Vertical */}
<ScrollArea className="h-72 w-48 rounded-md border">
<div className="p-4">
<h4 className="mb-4 text-sm font-medium leading-none">Tags</h4>
{tags.map((tag) => (
<div key={tag}>
<p className="text-sm">{tag}</p>
<Separator className="my-2" />
</div>
))}
</div>
</ScrollArea>
{/* Horizontal */}
<ScrollArea className="w-64 rounded-md border">
<div className="flex gap-4 p-4">
{artworks.map((artwork) => (
<figure key={artwork.title} className="shrink-0">
<div className="overflow-hidden rounded-md"><div className="size-[150px] bg-muted" /></div>
<figcaption className="pt-2 text-xs text-muted-foreground">
<span className="font-medium text-foreground block truncate w-[150px]">{artwork.title}</span>
{artwork.artist}
</figcaption>
</figure>
))}
</div>
<ScrollBar orientation="horizontal" />
</ScrollArea>
</div>
);Horizontal
Add a <ScrollBar orientation="horizontal" /> inside ScrollArea to enable horizontal scrolling. Both scrollbars can coexist.
<ScrollArea className="w-96 rounded-md border whitespace-nowrap">
<div className="flex gap-4 p-4">
{items.map((item) => (
<div key={item} className="shrink-0 w-40 h-20 rounded-md bg-muted" />
))}
</div>
<ScrollBar orientation="horizontal" />
</ScrollArea>Fixed height
Always set a fixed height (or max-height) on the ScrollArea — without a constraint the container expands to fit its content and nothing scrolls.
<ScrollArea className="h-64 w-full rounded-md border">
{/* long content */}
</ScrollArea>Both axes
Include both ScrollBar components for a two-dimensional scroll area.
<ScrollArea className="h-72 w-96 rounded-md border">
<div className="w-[600px]">{/* wide + tall content */}</div>
<ScrollBar orientation="horizontal" />
</ScrollArea>Props
ScrollArea
Extends all RadixScrollArea.Root props. Always set a height via className or style — the root is position: relative and the viewport fills it with size-full.
ScrollBar
| Prop | Type | Default | Description |
|---|---|---|---|
orientation | "vertical" | "horizontal" | "vertical" | Which axis this scrollbar controls |
className | string | — | Merged with the scrollbar track classes |
Usage
import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area";
<ScrollArea className="h-72 w-48 rounded-md border">
<div className="p-4">
{items.map((item) => (
<p key={item} className="text-sm py-1">{item}</p>
))}
</div>
</ScrollArea>Specs
# Mint — Scroll Area Specs
## Component
- name: scroll-area
- file: registry/mint/scroll-area.tsx
- installs to: components/ui/scroll-area.tsx
- dependencies: radix-ui
- registryDependencies: none
## What is it
A scrollable container that replaces native OS scrollbars with a consistent,
minimal custom design. Use it whenever overflowing content needs to be
scrollable with a predictable scrollbar appearance across platforms. Prefer
it over overflow-auto when visual consistency of the scrollbar track matters.
## Visual identity
Thin 2.5-unit (10px) scrollbar track with a transparent border that acts as
padding, giving the thumb a floating feel. The thumb uses --border — a soft,
translucent green tint — for a light touch that works across light and dark
themes without drawing attention.
## Design tokens
--border: oklch(0.88 0.04 155 / 60%) / oklch(0.32 0.05 155 / 40%) — scrollbar thumb colour
--ring: oklch(0.5 0.14 155) / oklch(0.62 0.15 155) — green viewport focus ring
## Sub-components
- ScrollArea → Root wrapper; position relative; auto-includes a vertical ScrollBar and Corner
- ScrollBar → Scrollbar track; 2.5-unit wide (vertical) or tall (horizontal); transparent border acts as inset padding
- (Viewport) → Internal; fills root with size-full; inherits border-radius; receives focus ring on keyboard scroll
- (Thumb) → Internal; bg-border, rounded-full; sized by Radix proportional to content ratio
- (Corner) → Internal; fills the gap when both vertical and horizontal scrollbars are present
## States
- focus-visible: viewport receives a 3px ring in --ring colour with ring/50 opacity on keyboard navigation
- data-[state=visible]: Radix shows the scrollbar when content overflows; hidden otherwise
- data-[orientation=vertical]: scrollbar is h-full w-2.5 with border-l
- data-[orientation=horizontal]: scrollbar is h-2.5 flex-col with border-t
## Conventions
- ScrollArea must have a constrained height (h-*, max-h-*) or the container expands to fit content and nothing scrolls
- A vertical ScrollBar is auto-rendered inside ScrollArea — do not add a second one
- For horizontal scrolling, add <ScrollBar orientation="horizontal" /> explicitly inside ScrollArea
- For two-axis scrolling, include both orientations; the Corner fills the overlap gap automatically
- Sub-components expose data-slot attributes for CSS targeting: "scroll-area", "scroll-area-viewport", "scroll-area-scrollbar", "scroll-area-thumb"
- Add whitespace-nowrap on the inner container to prevent line wrapping when using horizontal scrollInstallation
$ npx shadcn add \https://gin-design.vercel.app/scroll-area