Scroll Area
Use scroll area with the current published Askr packages.
@askrjs/ui/scroll-area0.0.13@askrjs/themes/scroll-area0.0.13
How to use scroll area
Scroll Area should use the standard themed surface unless the application is deliberately implementing its own design system on top of @askrjs/ui.
- Import the themed component from @askrjs/themes/components; use @askrjs/ui directly only when building a custom visual system.
- Keep scroll area labels, state, and application actions visible at the call site instead of styling internal DOM nodes.
- Verify keyboard behavior, focus movement or return, disabled state, and both standard themes.
import { ScrollArea, ScrollAreaScrollbar, ScrollAreaThumb, ScrollAreaViewport } from '@askrjs/themes/components';
<ScrollArea class="activity-log">
<ScrollAreaViewport>{events.map((event) => <ActivityRow event={event} />)}</ScrollAreaViewport>
<ScrollAreaScrollbar orientation="vertical"><ScrollAreaThumb /></ScrollAreaScrollbar>
</ScrollArea>Purpose
Scroll Area belongs to the ui & components layer. Use it when that layer owns the lifecycle or contract; keep simpler local behavior in state or ordinary components, and move network or request authority to the server boundary.
Install and import
Import ScrollArea, ScrollAreaViewport, ScrollAreaScrollbar, ScrollAreaThumb, and ScrollAreaCorner from @askrjs/ui/scroll-area, or the same five names pre-styled from @askrjs/themes/scroll-area, which re-exports the ui components as-is and depends entirely on CSS for appearance. Load @askrjs/themes/default for the actual visuals — the components alone only supply structure and shared IDs, no styling.
Live examples
A typical instance is ScrollArea wrapping a ScrollAreaViewport that holds your scrollable content, alongside a ScrollAreaScrollbar containing a ScrollAreaThumb, with an optional ScrollAreaCorner when both axes scroll. It's the shape you'd reach for around a tall settings panel, a chat sidebar, or any fixed-height region where you want scrolling to feel consistent with the theme's tokens rather than the raw OS scrollbar.
Anatomy
ScrollArea itself renders no DOM — it's a context provider that generates and shares related IDs (viewport, scrollbar, thumb, corner) across its children, and throws if any part is used outside a ScrollArea. ScrollAreaViewport renders the actual overflow: auto element that does the real scrolling; ScrollAreaScrollbar, ScrollAreaThumb, and ScrollAreaCorner are separate divs positioned by CSS, not children of the viewport itself.
State model
ScrollAreaViewport is ultimately just a plain scrollable div, so scrollTop and scrollLeft sit in the DOM the same way they would for any natively-scrolled element — the components aren't tracking scroll position themselves. To read or set scroll position from code, attach a ref to ScrollAreaViewport and reach for the standard DOM scroll APIs directly. Unlike Virtual List, there's no apiRef or imperative handle offered here.
Keyboard and accessibility
Because ScrollAreaViewport is a genuinely scrollable element, arrow keys, Page Up/Down, Home/End, and wheel scrolling all work through native browser behavior once the viewport or its content is focusable — nothing custom is layered on top. ScrollAreaScrollbar and ScrollAreaCorner are marked aria-hidden="true", since they're decorative visual elements sitting alongside the real scrollable region rather than a custom scrollbar widget assistive tech needs to know about.
Styling and tokens
The default theme's real interactive scrollbar is the native one: [data-slot="scroll-area-viewport"] gets scrollbar-width: thin and scrollbar-color set to --ak-color-border-strong, so the browser's own scrollbar is themed directly. ScrollAreaScrollbar and ScrollAreaThumb get basic track/thumb styling (width, radius, background) from the default CSS but aren't wired up to track actual scroll position or size — there's no JS syncing them to the viewport's scroll offset, so as shipped they read as a static visual accent rather than a functioning custom-drag scrollbar.
API
ScrollAreaProps takes just children and an optional id, used to derive the shared part IDs. ScrollAreaViewportProps, ScrollAreaScrollbarProps (which adds orientation?: 'vertical' | 'horizontal'), ScrollAreaThumbProps, and ScrollAreaCornerProps each extend the native div's props, so every part accepts ordinary HTML attributes plus asChild where the type allows it.
Edge cases
Every part throws if rendered outside a ScrollArea, since they all read shared IDs from context — you can't reuse ScrollAreaViewport or ScrollAreaThumb standalone. Because ScrollAreaScrollbar and ScrollAreaThumb aren't functionally linked to the viewport's scroll position in the shipped CSS, don't rely on them as your only scroll indicator if precise progress feedback matters — the native thin scrollbar on the viewport is the part that actually reflects how far the user has scrolled.
Related pages
See Virtual List and Virtual Table if what you actually need is windowed rendering for a large dataset rather than just a styled scroll region. See Table for content commonly placed inside a Scroll Area when it's wider or taller than its container.