MD3
Expressive
MATERIAL DESIGN 3 EXPRESSIVE

Scroll Area

Custom scrollbar component that provides a consistent, MD3 Expressive look and feel across all browsers.

The Scroll Area component augments native scroll functionality with a minimal, pill-shaped scrollbar that follows Material Design 3 Expressive guidelines. It ensures that scrollbars look and behave identically across different operating systems and browsers.

Loading demo...

Introduction

Native scrollbars often conflict with modern UI designs, appearing bulky or inconsistent across platforms. The MD3 Expressive Scroll Area solves this by providing a highly customizable, themeable scrollbar that only appears when needed. It is built on top of Radix UI's Scroll Area primitives, ensuring high performance and excellent accessibility.

Anatomy

  • Viewport: The visible area containing the scrollable content.
  • Scrollbar: The track and thumb used to navigate the content.
  • Thumb: The pill-shaped indicator that moves as the user scrolls.
  • Corner: The intersection where both horizontal and vertical scrollbars meet.

Variants

Orientations

  • Vertical (Default): For content that exceeds the height of its container.
  • Horizontal: For wide content like data tables or image galleries.
  • Both: Enables both vertical and horizontal scrolling with a dedicated corner element.
Loading demo...

Features

Visibility Behaviors

Control when the scrollbar is displayed using the type prop:

  • Hover (Default): Scrollbar appears only when the mouse is over the container.
  • Always: Scrollbar is permanently visible.
  • Scroll: Appears only while scrolling and hides after a delay.
  • Auto: Appears when the content exceeds the container size.
Loading demo...

Expressive Styling

The scrollbar thumb is a thin, pill-shaped element that subtly expands or highlights when interacted with, maintaining a clean and unobtrusive aesthetic.

Usage

Basic Usage

import { ScrollArea } from "@bug-on/m3-expressive";

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

Best Practices

Do

  • Use Scroll Area for containers with a fixed height where content may overflow.
  • Prefer type="hover" for clean interfaces where scrollability is obvious.
  • Use type="always" for critical scrollable areas (like sidebars) where the user needs to see the scroll progress at all times.
  • Set a clear max-height or height on the Scroll Area container.

Don't

  • Don't use Scroll Area for the entire page body; let the browser handle top-level scrolling.
  • Don't use orientation="both" if only one axis is likely to overflow.
  • Avoid nesting multiple Scroll Areas within each other, as it can be confusing for users to navigate.

Accessibility

  • Roles: Correctly implements ARIA roles for scroll containers and regions.
  • Keyboard: Supports standard keyboard navigation (Arrow keys, Page Up/Down, Home/End).
  • Touch: Provides native-feeling momentum scrolling on touch devices.
  • Visibility: The scrollbar is a visual aid and doesn't replace native accessibility features.

API Reference

ScrollArea

PropTypeDefaultDescription
type"auto" | "always" | "scroll" | "hover" | "none""hover"Visibility behavior.
orientation"vertical" | "horizontal" | "both""vertical"Scroll axis.
scrollHideDelaynumber600Hide delay (ms) for type="scroll".
classNamestringCustom classes.