Skip to main content

scroll area

Augments native scroll functionality for custom, cross-browser styling.

Philosophy

Native scrollbars break visual consistency across platforms. ScrollArea provides custom-styled scrollbars that behave identically everywhere while preserving native scroll physics. We keep the API minimal — just viewportClassName — because scrolling should be invisible infrastructure, not a feature you configure.

Installation


npx @gentleduck/cli add scroll-area

npx @gentleduck/cli add scroll-area
global.css
/* Add this block of css to your project. */
::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
 
::-webkit-scrollbar-track {
  background: transparent;
}
 
::-webkit-scrollbar-corner {
  background: transparent;
}
 
::-webkit-scrollbar-thumb {
  /* Replace this with your own custom scrollbar thumb color */
  background: var(--border);
  border-radius: 5px;
}
global.css
/* Add this block of css to your project. */
::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
 
::-webkit-scrollbar-track {
  background: transparent;
}
 
::-webkit-scrollbar-corner {
  background: transparent;
}
 
::-webkit-scrollbar-thumb {
  /* Replace this with your own custom scrollbar thumb color */
  background: var(--border);
  border-radius: 5px;
}

Usage

import { ScrollArea } from "@/components/ui/scroll-area"
import { ScrollArea } from "@/components/ui/scroll-area"
<ScrollArea className="h-[200px] w-[350px] rounded-md border p-4">
  Jokester began sneaking into the castle in the middle of the night and leaving
  jokes all over the place: under the king's pillow, in his soup, even in the
  royal toilet. The king was furious, but he couldn't seem to stop Jokester. And
  then, one day, the people of the kingdom discovered that the jokes left by
  Jokester were so funny that they couldn't help but laugh. And once they
  started laughing, they couldn't stop.
</ScrollArea>
<ScrollArea className="h-[200px] w-[350px] rounded-md border p-4">
  Jokester began sneaking into the castle in the middle of the night and leaving
  jokes all over the place: under the king's pillow, in his soup, even in the
  royal toilet. The king was furious, but he couldn't seem to stop Jokester. And
  then, one day, the people of the kingdom discovered that the jokes left by
  Jokester were so funny that they couldn't help but laugh. And once they
  started laughing, they couldn't stop.
</ScrollArea>

Examples

Horizontal Scrolling

API Reference

ScrollArea

PropTypeDefaultDescription
dir'ltr' | 'rtl'--Text direction override. Resolved via useDirection (dir prop -> DirectionProvider -> 'ltr').
viewportRefReact.Ref<HTMLDivElement>--Ref forwarded to the inner scrollable viewport element
viewportClassNamestring--Additional CSS classes for the inner scrollable viewport
classNamestring--Additional CSS classes for the outer container
styleReact.CSSProperties--Inline styles for the outer container
childrenReact.ReactNode--Scrollable content
...propsReact.HTMLProps<HTMLDivElement>--Additional props to spread to the content div

RTL Support

Direction is resolved through the shared primitives direction module. Use a local dir="rtl" override when the component exposes it, or set DirectionProvider at app/root level for global RTL/LTR behavior.