Components

Scroll Area

Augments native scroll with a slim, themed scrollbar that appears on interaction — keeping overflowing content contained without the browser's default chrome.

Basic usage

Give the ScrollArea a fixed height so taller content scrolls vertically inside it — without one there is nothing to scroll. A vertical ScrollBar and the corner are rendered for you; the viewport inherits the root's rounding, so a rounded-lg border on the root clips the content to match.

  • v2.4.0 — Added ScrollArea and ScrollBar primitives
  • v2.3.1 — Fixed focus ring offset on Viewport
  • v2.3.0 — New gold ring tokens for focus-visible states
  • v2.2.0 — Dialog now traps focus correctly
  • v2.1.4 — Tooltip arrow alignment fix
  • v2.1.3 — Button loading spinner contrast bump
  • v2.1.2 — Tabs underline animation timing
  • v2.1.1 — Accordion chevron rotation easing
  • v2.1.0 — Introduced Command palette component
  • v2.0.0 — Migrated to Tailwind v4 tokens
  • v1.9.2 — Select dropdown z-index fix
  • v1.9.1 — Avatar fallback initials sizing
  • v1.9.0 — Added Skeleton loading component
  • v1.8.0 — Breadcrumb separator slot support

Horizontal scrolling

Add a <ScrollBar orientation="horizontal" /> and a fixed width to scroll a row sideways.

DesignEngineeringProductMarketingSalesFinanceLegalOperationsSupportResearchDataSecurity

Scrollbar visibility

The scrollbar appears on hover by default and fades out again after scrollHideDelay. Set type="always" where the fact that a region scrolls at all is the information — a short list inside a dialog, a log pane — so nothing hides the only cue that there is more below.

  • v2.4.0 — Added ScrollArea and ScrollBar primitives
  • v2.3.1 — Fixed focus ring offset on Viewport
  • v2.3.0 — New gold ring tokens for focus-visible states
  • v2.2.0 — Dialog now traps focus correctly
  • v2.1.4 — Tooltip arrow alignment fix
  • v2.1.3 — Button loading spinner contrast bump
  • v2.1.2 — Tabs underline animation timing
  • v2.1.1 — Accordion chevron rotation easing
  • v2.1.0 — Introduced Command palette component
  • v2.0.0 — Migrated to Tailwind v4 tokens
  • v1.9.2 — Select dropdown z-index fix
  • v1.9.1 — Avatar fallback initials sizing
  • v1.9.0 — Added Skeleton loading component
  • v1.8.0 — Breadcrumb separator slot support

Props

ScrollArea

PropTypeDefaultDescription
classNamestringTailwind classes merged onto the root. Set a fixed height/width here (e.g. h-48 w-72) to enable scrolling.
childrenrequiredReact.ReactNodeContent rendered inside the scrollable viewport.
type'auto' | 'always' | 'scroll' | 'hover''hover'When the scrollbar is visible — auto: whenever the content overflows; always: permanently; scroll: only while scrolling; hover: only while hovering or scrolling.
scrollHideDelaynumber600Milliseconds before the scrollbar hides again. Only applies to the hover and scroll types.
dir'ltr' | 'rtl'Reading direction; flips the scrollbar to the correct side.
...restScrollArea.Root propsAll Radix ScrollArea Root props are forwarded to the root, which carries data-slot="scroll-area". The viewport is rendered internally, so viewport-only props such as nonce cannot be passed through here.

ScrollBar

PropTypeDefaultDescription
orientation'vertical' | 'horizontal''vertical'Axis the scrollbar controls. A vertical bar is already rendered by ScrollArea — add a ScrollBar yourself only for the horizontal axis.
forceMounttrueKeeps the scrollbar mounted so an external animation library can drive its enter/exit. Radix types it as the literal true — omit it rather than passing false.
classNamestringMerged onto the 10 px track. The thumb inside is bg-control-edge and is not separately exposed.
...restScrollAreaScrollbar propsAll Radix ScrollAreaScrollbar props are forwarded; the element carries data-slot="scroll-area-scrollbar".

Accessibility

  • Once the viewport has focus, Arrow, Page Up/Down, and Home/End scroll it natively. Radix does not put a tabIndex on the viewport, so whether it lands in the tab order is up to the browser's keyboard-focusable-scroller behaviour — keep focusable content (links, buttons) inside a long region so keyboard users can always reach the bottom of it.
  • The viewport carries a focus-visible ring in the gold --ring token, offset against --background, so the state is styled wherever a browser does expose it.
  • The thumb is painted with --control-edge, not --border. It is a draggable control and a position indicator, so it owes WCAG 1.4.11 3:1. The role token is what lets data-contrast="high" pay that in one place: 3.83:1 in light, 4.94:1 in dark. On the default palette --control-edge resolves to --input: the same #EDEEF1 step as border in light (1.16:1), but #434A5A in dark (2.00:1) where border sits at 1.10:1 — a known gap of that palette.
  • Built on Radix ScrollArea, which preserves native scroll semantics and assistive-technology behavior rather than replacing scrolling with JavaScript.
  • Touch and trackpad gestures continue to work normally — the custom scrollbar is purely visual and never blocks pointer or wheel input.