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.
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.
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.
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-heightorheighton 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
| Prop | Type | Default | Description |
|---|---|---|---|
type | "auto" | "always" | "scroll" | "hover" | "none" | "hover" | Visibility behavior. |
orientation | "vertical" | "horizontal" | "both" | "vertical" | Scroll axis. |
scrollHideDelay | number | 600 | Hide delay (ms) for type="scroll". |
className | string | — | Custom classes. |