LayoutReact
A native scroll container with custom scrollbars.
Rendered by React 19.3.1
Installation
npm i @hamur/reactNot on npm yet. The package goes out under the chosen name.
Anatomy
Import the component and assemble its parts:
<ScrollArea.Root>
<ScrollArea.Viewport>
<ScrollArea.Content />
</ScrollArea.Viewport>
<ScrollArea.Scrollbar>
<ScrollArea.Thumb />
</ScrollArea.Scrollbar>
</ScrollArea.Root>
// Not in this example: ScrollArea.CornerExamples
Both
Two scrollbars, with Corner where they meet.
Scroll Fade
The overflow CSS variables drive a mask that fades the edges.
API reference
3 props across 6 parts, in React syntax. className, style, render are listed once, under Shared props.
ContentScrollArea.Content
A container for the content of the scroll area. Renders a <div>.
| Data attribute | Description |
|---|---|
data-scrolling | Present when the user scrolls inside the scroll area. |
data-has-overflow-x | Present when the scroll area content is wider than the viewport. |
data-has-overflow-y | Present when the scroll area content is taller than the viewport. |
data-overflow-x-start | Present when there is overflow on the horizontal start side. |
data-overflow-x-end | Present when there is overflow on the horizontal end side. |
data-overflow-y-start | Present when there is overflow on the vertical start side. |
data-overflow-y-end | Present when there is overflow on the vertical end side. |
CornerScrollArea.Corner
A small rectangular area that appears at the intersection of horizontal and vertical scrollbars. Renders a <div>.
RootScrollArea.Root
Groups all parts of the scroll area. Renders a <div>.
| Prop | Type | Default |
|---|---|---|
overflowEdgeThresholdThe threshold in pixels that must be passed before the overflow edge attributes are applied. | number | Partial<{ xStart: number; xEnd: number; yStart: number; yEnd: number; }> | 0 |
| Data attribute | Description |
|---|---|
data-scrolling | Present when the user scrolls inside the scroll area. |
data-has-overflow-x | Present when the scroll area content is wider than the viewport. |
data-has-overflow-y | Present when the scroll area content is taller than the viewport. |
data-overflow-x-start | Present when there is overflow on the horizontal start side. |
data-overflow-x-end | Present when there is overflow on the horizontal end side. |
data-overflow-y-start | Present when there is overflow on the vertical start side. |
data-overflow-y-end | Present when there is overflow on the vertical end side. |
| CSS variable | Description |
|---|---|
--scroll-area-corner-height | The scroll area's corner height. |
--scroll-area-corner-width | The scroll area's corner width. |
ScrollbarScrollArea.Scrollbar
A vertical or horizontal scrollbar for the scroll area. Renders a <div>.
| Prop | Type | Default |
|---|---|---|
orientationWhether the scrollbar controls vertical or horizontal scroll. | "horizontal" | "vertical" | 'vertical' |
keepMountedWhether to keep the HTML element in the DOM when the viewport isn't scrollable. | boolean | false |
| Data attribute | Description |
|---|---|
data-orientation | Indicates the orientation of the scrollbar. |
data-hovering | Present when the pointer is over the scroll area. |
data-scrolling | Present when the user scrolls inside the scroll area. |
data-has-overflow-x | Present when the scroll area content is wider than the viewport. |
data-has-overflow-y | Present when the scroll area content is taller than the viewport. |
data-overflow-x-start | Present when there is overflow on the horizontal start side. |
data-overflow-x-end | Present when there is overflow on the horizontal end side. |
data-overflow-y-start | Present when there is overflow on the vertical start side. |
data-overflow-y-end | Present when there is overflow on the vertical end side. |
| CSS variable | Description |
|---|---|
--scroll-area-thumb-height | The scroll area thumb's height. |
--scroll-area-thumb-width | The scroll area thumb's width. |
ThumbScrollArea.Thumb
The draggable part of the scrollbar that indicates the current scroll position. Renders a <div>.
| Data attribute | Description |
|---|---|
data-orientation | Indicates the orientation of the scrollbar. |
data-scrolling | Present when the user scrolls inside the scroll area. |
ViewportScrollArea.Viewport
The actual scrollable container of the scroll area. Renders a <div>.
| Data attribute | Description |
|---|---|
data-scrolling | Present when the user scrolls inside the scroll area. |
data-has-overflow-x | Present when the scroll area content is wider than the viewport. |
data-has-overflow-y | Present when the scroll area content is taller than the viewport. |
data-overflow-x-start | Present when there is overflow on the horizontal start side. |
data-overflow-x-end | Present when there is overflow on the horizontal end side. |
data-overflow-y-start | Present when there is overflow on the vertical start side. |
data-overflow-y-end | Present when there is overflow on the vertical end side. |
| CSS variable | Description |
|---|---|
--scroll-area-overflow-x-start | The distance from the horizontal start edge in pixels. |
--scroll-area-overflow-x-end | The distance from the horizontal end edge in pixels. |
--scroll-area-overflow-y-start | The distance from the vertical start edge in pixels. |
--scroll-area-overflow-y-end | The distance from the vertical end edge in pixels. |
Shared props
Every part that renders an element takes these.
| Prop | Type |
|---|---|
classNameCSS class applied to the element, or a function that
returns a class based on the component's state. | string | ((state: State) => string | undefined) |
styleStyle applied to the element, or a function that
returns a style object based on the component's state. | React.CSSProperties | ((state: State) => React.CSSProperties | undefined) |
renderAllows you to replace the component's HTML element
with a different tag, or compose it with another component. | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, State> |
Keyboard and accessibility
Keyboard
ScrollArea adds no keys: Viewport takes focus when its content overflows, and the browser scrolls it with the arrow keys, PageUp, PageDown, Home and End.
Accessibility
| Part | Sets | So that |
|---|---|---|
| Viewport | tabindex="0" while the content overflows | keyboard users can focus the region and scroll it |
| Viewport | keeps its own role | the scrollable region is not hidden from assistive technology |
| Scrollbar | aria-hidden="true" | the custom bars are not read; the native scroll position is |
| Corner | aria-hidden="true" | the corner piece is not read |
| Root | role="presentation" | the wrapper adds nothing to what is read |
| Content | role="presentation" | the inner wrapper adds nothing to what is read |
Focus order
- Viewport is a tab stop only while its content overflows; the content's own controls follow in order.