Light

Scroll Area

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

Spec · from metadata

When to use

  • Containing content that overflows with styled scrollbars matching the design system
  • Scrollable dropdown menus, sidebars, or panels
  • Anywhere you need consistent cross-browser scrollbar appearance

When not to use

  • For full-page scrolling — use the browser's native scroll instead
  • For horizontal content carousels — use Carousel instead
  • When native scrollbars are acceptable and no styling is needed

Anti-patterns

Avoid<ScrollArea>Long content...</ScrollArea>
Prefer<ScrollArea className="h-64">Long content...</ScrollArea>

Without a constrained height, ScrollArea expands to fit content and never scrolls

Avoid<ScrollArea className="h-64"><ScrollArea className="h-32">...</ScrollArea></ScrollArea>
Prefer<ScrollArea className="h-64">...</ScrollArea>

Nesting ScrollAreas causes conflicting scroll contexts and broken scrollbar behavior

Accessibility

  • Screen readerScrollbar is purely visual; content remains accessible via standard DOM order. The viewport has tabIndex for keyboard scrolling.
  • ContrastScrollbar thumb uses bg-border for visibility against content backgrounds

Token bindings

TokenCategoryUsage
bg-bordercolorScrollbar thumb color
w-2.5 / h-2.5spacingScrollbar track width (vertical) or height (horizontal)

Import

import { ScrollArea, ScrollBar } from "@timelycare/helix-ui"

Props

interface ScrollAreaProps {
  type?: "auto" | "always" | "scroll" | "hover"
  scrollHideDelay?: number    // ms before scrollbar hides
  className?: string
  children: React.ReactNode
}

interface ScrollBarProps {
  orientation?: "vertical" | "horizontal"
  className?: string
}

Structure

PartTailwind
ScrollArea rootrelative overflow-hidden
Viewporth-full w-full rounded-[inherit]
Scrollbar trackflex touch-none select-none p-0.5 transition-colors
Scrollbar thumbrelative rounded-full bg-border
Vertical scrollbarh-full w-2.5 border-l border-l-transparent
Horizontal scrollbarh-2.5 w-full border-t border-t-transparent

Scrollbar Visibility

TypeBehavior
autoShows when content overflows, hides when idle
alwaysAlways visible when content overflows
scrollShows only while scrolling
hoverShows on hover when content overflows

Common Patterns

Vertical Scroll

<ScrollArea className="h-72 w-48 rounded-md border">
  <div className="p-4">
    {items.map((item) => (
      <div key={item} className="text-sm">{item}</div>
    ))}
  </div>
</ScrollArea>

Horizontal Scroll

<ScrollArea className="w-96 whitespace-nowrap rounded-md border">
  <div className="flex w-max gap-4 p-4">
    {items.map((item) => (
      <div key={item} className="w-40 shrink-0">{item}</div>
    ))}
  </div>
  <ScrollBar orientation="horizontal" />
</ScrollArea>

Both Directions

<ScrollArea className="h-72 w-96 rounded-md border">
  <div className="w-[600px] p-4">
    {/* Wide and tall content */}
  </div>
  <ScrollBar orientation="vertical" />
  <ScrollBar orientation="horizontal" />
</ScrollArea>

Tags/Chips Row

<ScrollArea className="w-full whitespace-nowrap">
  <div className="flex gap-2 pb-3">
    {tags.map((tag) => (
      <Badge key={tag} variant="secondary">{tag}</Badge>
    ))}
  </div>
  <ScrollBar orientation="horizontal" className="h-2" />
</ScrollArea>

Accessibility

  • Built on Radix ScrollArea — decorative scrollbar replacement
  • Keyboard: standard scroll behavior (Arrow keys, Page Up/Down, Home/End)
  • Screen reader: native scroll announcements preserved
  • Scrollbar is decorative — does not affect accessibility tree

Gotchas

ProblemSolution
Horizontal scroll not workingAdd whitespace-nowrap and explicit ScrollBar orientation="horizontal"
Content not filling widthInner content needs w-max or explicit width
Scrollbar always visibleDefault is auto; content must overflow to show
Border radius not inheritedAdd rounded-md to both ScrollArea and content wrapper

Note

This component is React-specific and has no Figma representation. It wraps Radix UI's ScrollArea primitive with custom styling for the scrollbar thumb (bg-border) and track.


See Also

  • Related Components: Resizable (resizable panels), Table (scrollable tables)
  • Patterns: Layouts — Scrollable container patterns

Last updated: February 9, 2026