ScrollView when arbitrary content can overflow a region. The toolkit owns the scroll viewport, boundary fades, floating single-axis scrollbar, keyboard scrolling, and focus reveal, which keeps focused content clear of each fade. The application provides the content and sizes the region.ScrollView with the standard row container for consistent list layout.import { ScrollView, TextStyle, TextView } from '@wearables-ui-toolkit/mrbd';
type ArticleBodyProps = {
paragraphs: string[];
};
export function ArticleBody({ paragraphs }: ArticleBodyProps) {
return (
<ScrollView ariaLabel="Article">
<div className="article-body">
{paragraphs.map((text, index) => (
<TextView as="p" key={index} textStyle={TextStyle.BODY2}>
{text}
</TextView>
))}
</div>
</ScrollView>
);
}
.article-body {
display: flex;
flex-direction: column;
gap: var(--uit-spacing-small);
padding-block: var(--uit-spacing-medium);
}
orientation. The component then switches both the scroll axis and the active pair of fades:import {
Card,
ScrollView,
ScrollViewOrientation,
} from '@wearables-ui-toolkit/mrbd';
type CaptureStripProps = {
captures: ReadonlyArray<{ id: string; label: string }>;
};
export function CaptureStrip({ captures }: CaptureStripProps) {
return (
<ScrollView
ariaLabel="Recent captures"
orientation={ScrollViewOrientation.HORIZONTAL}
scrollbarEnabled={false}
>
<div className="capture-row">
{captures.map(capture => (
<Card key={capture.id}>{capture.label}</Card>
))}
</div>
</ScrollView>
);
}
.capture-row {
display: flex;
gap: var(--uit-spacing-small);
padding-inline: var(--uit-spacing-medium);
}
ScrollViewProps. This is a closed prop set: ScrollView does not spread additional DOM attributes onto the frame or viewport, so callers can pass only the props below.| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | Scrollable content. |
orientation | ScrollViewOrientation | ScrollViewOrientation.VERTICAL | Active scroll axis. |
fadingEdgeEnabled | boolean | true | Draws fades at the boundaries of the active axis. Turning it off removes all fades and their focus-reveal insets. |
topFadingEdgeLength | number | Standard fade length | Top fade length in pixels. Applies only to vertical orientation. |
bottomFadingEdgeLength | number | Standard fade length | Bottom fade length in pixels. Applies only to vertical orientation. |
leftFadingEdgeLength | number | Standard fade length | Left fade length in pixels. Applies only to horizontal orientation. |
rightFadingEdgeLength | number | Standard fade length | Right fade length in pixels. Applies only to horizontal orientation. |
insetForHeader | boolean | false | Reserves top padding so content begins below an overlapping header. |
headerHeight | number | Standard header height | Reserved inset height in pixels. Set it to the overlapping header’s height. Used only when insetForHeader is set. |
scrollbarEnabled | boolean | true | Controls whether the single-axis scrollbar can appear. |
showScrollbar | boolean | — | Alias for scrollbarEnabled. scrollbarEnabled takes precedence when both are set; the scrollbar is on when neither is set. |
width | number or string | '100%' | Scroll frame width. |
height | number or string | '100%' | Scroll frame height. |
className | string | '' | Class applied to the outer frame. |
scrollContainerClassName | string | '' | Class applied to the scrolling viewport. |
style | CSSProperties | — | Inline styles applied to the outer frame. They merge after width and height, so a width or height here takes precedence. |
ariaLabel | string | — | Accessible name for the scroll region. |
tabIndex | number | -1 | Tab index of the scrolling viewport. |
onScroll | (scrollTop: number) => void | — | Runs on every scroll event with the viewport’s vertical scroll offset. |
scrollTop, scrollLeft, and scrollTo APIs directly.ScrollViewOrientationVERTICALHORIZONTALwidth, height, className, and style. Inside it, the scrolling viewport receives scrollContainerClassName, tabIndex, and the accessible name. A content element wraps the caller’s children and defines the region’s focus boundary. Fades and the scrollbar are viewport siblings, so they neither affect layout nor scroll with the content.orientation selects the only scrollable axis and the fade props the toolkit reads. For example, topFadingEdgeLength has no effect in a horizontal scroll view. In horizontal orientation, the content element becomes a top-aligned row sized to its content, so children follow the scroll axis. In vertical orientation, it is at least as tall as the viewport.PageUp and PageDown scroll by one viewport, and Home and End move to the boundaries. If an arrow key points past an already reached boundary, ScrollView asks the surrounding directional navigation system to move focus out of the region instead of consuming the key. PageUp, PageDown, Home, and End always remain with the region. Every keyboard scroll explicitly requests smooth behavior, which keeps motion consistent even when the host page sets a different scroll-behavior.ScrollView reveals it inside the active fade insets so a fade does not dim the focused content. If both insets cannot fit in the viewport, the toolkit shrinks them proportionally rather than consuming the region. For the first or last focusable element, the container settles at the true scroll boundary when that alignment keeps the element fully visible and clear of the active fade and header inset. If leading or trailing non-focusable content pushes the focused element outside that safe area, normal focus reveal takes precedence and outward arrow presses scroll the remaining content incrementally. The toolkit checks again after container animations settle so expansion does not move the focused element beneath an overlay. When the viewport cannot fit the element and all preferred fade insets, the toolkit contracts fade clearance while preserving header clearance as far as space allows. Avoid permanent padding intended only to move a boundary past a fade; the focus-reveal calculation already owns that clearance.ScrollView consumes the key and scrolls by up to half a viewport or the remaining distance, whichever is smaller. If a neighbor exists in that direction, the component leaves the key available while any part of the current focus remains within the physical viewport. Focus can then move to a partially visible neighbor, and normal focus reveal brings it clear of the fade. While the focused element is entirely outside the viewport, arrow presses continue scrolling instead of moving focus so the element can return to view first. The region’s own first and last focusable elements are the exception: when settling at the true boundary still keeps the element fully visible and clear of the active fade and header inset, the region snaps to that boundary and passes the key on. This lets focus leave a fully scrolled region instead of trapping it.ScrollView leaves reveal behavior to the inner region. This is a safety mechanism, not a supported composition. Use exactly one scroll container per axis. In particular, do not wrap a vertical ScrollView around a VerticalList, because both components would own vertical scrolling and focus reveal.insetForHeader, the toolkit gives the scrolling viewport top padding equal to headerHeight plus the content-origin offset from an enclosing Page, when present. Content then begins below an overlapping header while respecting the page’s content origin. Because the inset is viewport padding, fades and the scrollbar remain aligned with the frame.ScrollView remeasures its box when the box or its children change, keeping fades and the scrollbar accurate as content grows or shrinks. Prefer to size the parent from the available viewport rather than a fixed device size, which keeps the layout responsive.ariaLabel so the scrolling region has an accessible name; ScrollView does not infer one from its content.tabIndex defaults to -1. The region stays outside the tab sequence but can receive programmatic and directional-navigation focus. Set it to 0 only when the region itself needs to be a tab stop, typically when non-focusable content must remain keyboard-scrollable.aria-hidden, so assistive technology does not announce these decorative elements.ariaLabel that identifies what scrolls.onScroll as a vertical offset only. It always reports scrollTop; read the forwarded ref’s scrollLeft for a horizontal region.children, or target the viewport with scrollContainerClassName.