Layout and structure

ScrollArea
v1.0.6
Documentation Under Review

A custom scrollbar component for product interfaces with customizable styling via className overrides. Supports vertical/horizontal scrolling, container queries, and brand theming.

The Product ScrollArea component provides a styled alternative to native scrollbars optimized for product/application experiences. Built on Radix UI with support for custom styling via className overrides, container queries, and brand-specific theming.

Installation

Install the ScrollArea component from the Catalyst component library:

npm install '@pmi/catalyst-scroll-area'

Examples

Vertical Scrolling

Scroll vertically through content that exceeds container height.

Preview

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.

Custom Brand Styling

Apply custom brand colors to scrollbar and viewport using className overrides.

Preview

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.

Horizontal Scrolling

Scroll horizontally through wide content with horizontal scrollbar.

Preview
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

With Container Queries

Use CSS container queries within scroll area for responsive content.

Preview

Scroll area with container query

Resize your browser to see the background change when the container width exceeds the large breakpoint.

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

No scrolling example

This content doesn't overflow, so no scrollbar appears. Container query still works based on viewport width.

API Reference

ScrollAreaRoot

The root container for the scroll area with overflow handling.

Prop

Type

Default Styles:

  • Position: relative overflow-hidden
  • Group: group/scrollarea for hover states

ScrollAreaViewport

The scrollable viewport container for content.

Prop

Type

Default Styles:

  • Size: h-full w-full
  • Border: border border-transparent rounded-lg
  • Focus: focus-visible:ring-1 focus-visible:ring-pmi-off-black-800
  • Padding: p-0.5

Custom Styling Example:

<ScrollAreaViewport
  className="focus-visible:ring-pmi-aqua-500 focus-visible:border-pmi-aqua-500"
>
  {content}
</ScrollAreaViewport>

ScrollAreaScrollbar

The scrollbar track that appears on hover or always.

Prop

Type

Default Styles:

  • Layout: flex shrink-0 touch-none select-none
  • Background: group-hover/scrollarea:bg-pmi-neutral-100 (on hover)
  • Vertical: h-full w-2.5 p-0.5
  • Horizontal: h-2.5 flex-col p-0.5
  • Transition: transition-colors

Custom Styling Example:

<ScrollAreaScrollbar
  className="group-hover/scrollarea:bg-neutral-200 dark:group-hover/scrollarea:bg-neutral-700"
>

ScrollAreaThumb

The draggable thumb within the scrollbar.

Prop

Type

Default Styles:

  • Shape: relative flex-1 rounded-full
  • Background: bg-pmi-neutral-500, dark:bg-pmi-neutral-300

Custom Styling Example:

<ScrollAreaThumb className="bg-neutral-500 dark:bg-neutral-400" />

ScrollAreaCorner

The corner element where vertical and horizontal scrollbars meet.

Prop

Type

Design Tokens

The Product ScrollArea uses Tailwind design tokens with full customization support:

  • Default Scrollbar Track:
    • Hidden by default
    • bg-pmi-neutral-100 (light) on hover
    • bg-pmi-neutral-800 (dark) on hover
    • Width: w-2.5 (10px) vertical, h-2.5 horizontal
  • Default Thumb:
    • bg-pmi-neutral-500 (light mode)
    • bg-pmi-neutral-300 (dark mode)
    • Shape: rounded-full
  • Default Viewport Focus:
    • Ring: focus-visible:ring-1 ring-pmi-off-black-800
    • Border: focus-visible:border-pmi-off-black-800
  • Custom Colors: Any Tailwind color via className overrides
  • Transitions: transition-colors on scrollbar
  • Border Radius: Inherits from container (rounded-[inherit])

Custom Styling Pattern

The Product variant supports extensive customization:

import { cn } from '@pmi/catalyst-utils'

// Custom scrollbar track
const customScrollbar = cn(
  'group-hover/scrollarea:bg-neutral-200',
  'dark:group-hover/scrollarea:bg-neutral-700'
)

// Custom viewport focus
const customViewport = cn(
  'focus-visible:ring-pmi-aqua-500',
  'focus-visible:border-pmi-aqua-500',
  'dark:focus-visible:ring-pmi-aqua-500',
  'dark:focus-visible:border-pmi-aqua-500'
)

// Custom thumb
const customThumb = cn(
  'bg-neutral-500',
  'dark:bg-neutral-400'
)

// Apply to scroll area
<ScrollAreaViewport className={customViewport}>
  {content}
</ScrollAreaViewport>
<ScrollAreaScrollbar className={customScrollbar}>
  <ScrollAreaThumb className={customThumb} />
</ScrollAreaScrollbar>

Container Query Integration

Use CSS container queries for responsive content:

<ScrollAreaRoot className="h-[200px] w-full">
  <ScrollAreaViewport>
    <div className="@container/main">
      <div className="@lg/main:bg-blue-100 p-4">
        Content that changes at large container size
      </div>
    </div>
  </ScrollAreaViewport>
  <ScrollAreaScrollbar orientation="vertical">
    <ScrollAreaThumb />
  </ScrollAreaScrollbar>
</ScrollAreaRoot>

Accessibility

The Product ScrollArea component follows WCAG 2.1 AA accessibility standards:

  • Keyboard Navigation:
    • Viewport is focusable with tabIndex={0}
    • Arrow keys scroll content
    • Page Up/Down for larger scrolls
    • Home/End for start/end
  • Focus Indicators: Visible focus ring on viewport
  • Touch Support:
    • touch-none on scrollbar for proper touch handling
    • Native touch scrolling on viewport
  • Screen Reader Support:
    • Proper ARIA attributes from Radix UI
    • Scrollable region announced
  • Mouse Support:
    • Click scrollbar track to jump
    • Drag thumb to scroll
    • Scroll wheel support
  • RTL Support: dir prop for right-to-left layouts
  • Color Contrast: Default colors meet 4.5:1 contrast ratio minimum
  • Custom Theme Testing: Validate custom colors meet WCAG AA standards

Best Practices

  • Always include ScrollAreaScrollbar with orientation
  • Always include ScrollAreaThumb inside ScrollAreaScrollbar
  • Include ScrollAreaCorner when using both orientations
  • Set explicit height/width on ScrollAreaRoot
  • Use whitespace-nowrap for horizontal scrolling text
  • Use w-max for horizontal scrolling containers
  • Test keyboard navigation with Tab and arrow keys
  • Ensure sufficient color contrast on custom themes
  • Provide visual focus indicators
  • Test with screen readers
  • When using custom styles, verify color contrast meets WCAG AA (4.5:1)
  • Test custom brand colors in both light and dark modes
  • Use @container queries for responsive scrollable content

Differences from Marketing ScrollArea

The Product ScrollArea variant differs from the Marketing ScrollArea in the following ways:

FeatureMarketingProduct
Custom StylingStandard themingFull className override support
Use CaseMarketing pages, content areasProduct UIs, dashboards, data displays
ThemingFixed PMI colorsCustomizable brand colors
Examples3 standard4 including custom styling + container queries
DocumentationBasic implementationIncludes brand-specific patterns
  • ScrollArea - Marketing-focused variant
  • Sheet - Side panels that may use scroll areas
  • Dialog - Modals that may contain scrollable content
  • Popover - Popovers with scrollable content
  • Table - Tables with scrollable content

See Also

On this page