Scrollbar
The browser's own scrollbars, themed once for every scroll container in the application.
A scrollbar is drawn by the browser, so AsheeUI ships no Scrollbar component. It ships a
configuration entry and the stylesheet that reads it: the thickness of every scrollbar on the
page, the rounding of its thumb and track, the space the thumb keeps from the edge of the track,
the gutter reserved for it, and the two colours the theme supplies.
Set it once and every scroll container in the application wears it. There is nothing to render and no component to find in the gallery: the provider writes the values into variables on the document, and the stylesheet applies them.
Usage
State the entry under components in the configuration the provider receives:
import { AsheeUIProvider } from "@asheeui/web";
<AsheeUIProvider
config={{
components: {
scrollbar: { width: "12px", radius: "8px", thumbBorder: "2px" },
},
}}>
{children}
</AsheeUIProvider>;
Every key is optional, and the defaults apply where you state nothing, including on a page that
never mentions scrollbar at all, because the resolved configuration always carries the
registered defaults. The snippet above is therefore how a product with a heavier scrollbar is
configured, not the minimum required. An asheeui.config.ts file that exports the same object
works identically, as configuration describes.
The values are written into CSS custom properties on the document root before the first paint, by
the same script that writes the theme's colours: --ashee-scrollbar-width,
--ashee-scrollbar-radius, --ashee-scrollbar-track-radius, --ashee-scrollbar-thumb-border,
--ashee-scrollbar-gutter and --ashee-scrollbar-fallback-width. The stylesheet reads those
variables and never the configuration object, which is why a theme switch leaves them alone and
why a scroll container does not have to know the configuration exists.
Configuration
| Key | Takes | Default |
|---|---|---|
width |
Any CSS length: the thickness of the scrollbar, and the height of a horizontal one | "10px" |
radius |
Any CSS radius: the thumb's corners, and the track's while trackRadius is unstated |
"9999px" |
trackRadius |
Any CSS radius, for the track alone | Falls back to radius |
thumbBorder |
Any CSS length: drawn as a transparent border on the thumb plus padding-box clipping, so it reads as breathing room between thumb and track |
"3px" |
gutter |
"auto", "stable" or "stable both-edges": the native scrollbar-gutter value that reserves space for the scrollbar |
"stable" |
fallbackWidth |
"auto", "thin" or "none": the native scrollbar-width keyword for engines that draw the scrollbar themselves |
"thin" |
Colours are not among them. The thumb and track take the theme's scrollbarThumb and
scrollbarTrack colours, so they change with the theme rather than with this entry, and a theme
whose track is transparent, the light theme's, draws only the thumb. gutter: "stable" is
what stops a page shifting sideways when its content grows past a screen; "stable both-edges"
reserves the same room on both sides, for a centred column.
fallbackWidth is the bar an engine that draws its own scrollbar will take, written as the
scrollbar-width keyword the stylesheet reads from --ashee-scrollbar-fallback-width: thin
for the narrow bar the framework defaults to, auto for the engine's own thickness, and none
to draw no bar at all in a piece of content a reader still scrolls.
Where it applies
The stylesheet styles html, body and every element, so the scrollbar of a nested pane
follows the same entry as the page's own: a card with a scrolling body, a table with a pinned
header, a textarea with more text than rows. The width, the rounding and the thumb border come
from the values above; the two colours come from the active theme.
What does not follow it:
- The thickness and rounding are WebKit's. The width, the track radius and the thumb's
border are drawn through
::-webkit-scrollbar,::-webkit-scrollbar-trackand::-webkit-scrollbar-thumb, which Chromium and WebKit implement. An engine without those pseudo-elements, Firefox, gets the standardscrollbar-colorandscrollbar-widthinstead, so it takes the colours and thefallbackWidthbar, and its exact thickness and rounding are the browser's own. - Overlay scrollbars belong to the platform. Where the operating system draws a scrollbar over the content and fades it out, macOS's default, iOS, the platform paints it and may use none of this. No CSS can insist on a classic scrollbar there.
- A frame is another document. The scrollbar of an
iframebelongs to the page inside it, and takes this stylesheet only if that page loads AsheeUI's styles. - A container can opt out. The stylesheet also provides
.scrollbar-hide, which keeps the element scrollable but setsscrollbar-width: none, hides the WebKit pseudo-elements and returns the gutter toauto;.scrollable-hiddenis the earlier spelling of the same idea, without the gutter reset. The framework's own carousels, overlay backdrops and toast stacks carry the class, because a scrollbar there is noise. Everything else, the body, a page's own panes, is styled.
An element that cannot scroll has nothing to draw, so the entry is invisible until content overflows: no configuration is required for a page that never scrolls.
Accessibility
- The two colours come from the theme, and the default track is transparent, so the thumb alone
carries the scrollbar's contrast against the background. Keeping that pair readable is what
scrollbarThumbandscrollbarTrackare for; the configuration entry changes shape, not contrast. - The scrollbar is the browser's control: it is not focusable and not announced, and
widthis not a target-size guarantee. Scrolling also has to work from the keyboard and the wheel, which is the browser's behaviour and the reason nothing here removesoverflow. scrollbar-hideremoves the indicator, not the scrolling: the reader loses the only thing that said how much of the content is left. Use it where something else answers that question, a carousel's arrows, a marquee, a list with a count beside it, and not on a page's only scroller.gutter: "stable"reserves the scrollbar's room before it is needed, so content does not reflow when a page grows; a layout that measures itself on load should keep it.
Native
The platform draws its own scroll indicator, so there is no entry in the compatibility matrix and
nothing to import: a React Native ScrollView can show or hide its indicator, but its shape and
colours are the platform's. See React Native.