Scroll Bar
A scroll bar is a UI component that allows users to navigate vertically or horizontally through content that extends beyond the visible area of a container. The ScrollBar component provides a headless scrollbar track element with proper ARIA scrollbar semantics, including orientation, value range, and accessible labeling.
This component renders the structural markup and ARIA attributes for a custom scrollbar. The consumer provides the visual thumb element as children and is responsible for implementing the scroll interaction logic (drag handling, position updates, and syncing with scrollable content). The component sets initial value attributes that the consumer should update dynamically.
Example
Show demo markup
<div class="scroll-bar" role="scrollbar" aria-valuenow="50"></div>
Usage example
<script lang="ts">
import ScrollBar from "./ScrollBar.svelte";
</script>
<ScrollBar orientation="vertical" label="Page scroll">
<div class="thumb"></div>
</ScrollBar>
Show Svelte source
// In your Svelte component:
import ScrollBar from "lily-design-system-svelte-headless/components/ScrollBar/ScrollBar.svelte";
<ScrollBar>
<!-- list children -->
</ScrollBar>
Usage
Vertical scrollbar inside a chat message area:
<ScrollArea label="Chat messages" style="max-height: 400px; overflow: auto;">
<div class="messages"><!-- chat messages --></div>
<ScrollBar orientation="vertical" label="Chat scroll">
<div class="scroll-thumb"></div>
</ScrollBar>
</ScrollArea>
Horizontal scrollbar for a timeline strip:
<ScrollArea label="Project timeline" style="overflow-x: auto;">
<div class="timeline"><!-- timeline content --></div>
<ScrollBar orientation="horizontal" label="Timeline scroll">
<div class="scroll-thumb"></div>
</ScrollBar>
</ScrollArea>
Props
orientation: "vertical" | "horizontal" (default: "vertical") -- the scrollbar direction, reflected in aria-orientation
label: string (required) -- accessible name for the scrollbar via aria-label
children: slot (required) -- scrollbar content, typically the draggable thumb element
...restProps: unknown -- additional attributes spread onto the <div> element
Keyboard Interactions
- Arrow Up / Arrow Left: Scroll backward (decrease value) by a small increment
- Arrow Down / Arrow Right: Scroll forward (increase value) by a small increment
- Page Up: Scroll backward by a large increment
- Page Down: Scroll forward by a large increment
- Home: Scroll to the beginning (minimum value)
- End: Scroll to the end (maximum value)
Note: The consumer is responsible for implementing keyboard event handlers that update the scrollbar value.
ARIA
role="scrollbar" -- identifies the element as a scrollbar control
aria-label="..." -- provides the accessible name for the scrollbar
aria-orientation="vertical|horizontal" -- indicates the scrollbar direction
aria-valuenow="0" -- the current scroll position (consumer should update dynamically)
aria-valuemin="0" -- the minimum scroll value
aria-valuemax="100" -- the maximum scroll value
When to Use
- Use ScrollBar as a custom-styled scrollbar element within a ScrollArea container.
- Use ScrollBar when the native scrollbar appearance does not match your design system and you need visual consistency.
- Use ScrollBar to provide a scrollbar with full ARIA semantics for assistive technology users.
When Not to Use
- Do not use ScrollBar outside of a ScrollArea -- it requires the scroll container context for proper functionality.
- Do not use ScrollBar when native scrollbars are sufficient -- custom scrollbars add implementation complexity for drag handling and position synchronization.
Headless
The ScrollBar headless component provides a <div> with role="scrollbar", aria-orientation, aria-valuenow, aria-valuemin, aria-valuemax, and aria-label for full ARIA scrollbar semantics. The consumer provides the visual thumb element, drag interaction logic, and position synchronization with scrollable content.
Styles
The consumer provides all CSS styling. The component renders with a .scroll-bar class for targeting. No default styles are included — this is a fully headless component.
Testing
- Verify the component renders a
<div> element with class scroll-bar
- Verify role="scrollbar"` -- identifies the element as a scrollbar control
- Verify aria-label="..."` -- provides the accessible name for the scrollbar
- Verify keyboard interactions work correctly
- Verify pass-through attributes are applied
Advice
- Designers: Make the scrollbar thumb large enough to grab easily, and ensure sufficient contrast between the thumb and track for visibility.
- Developers: Update
aria-valuenow dynamically as the user scrolls, and implement keyboard event handlers for arrow keys, Page Up/Down, Home, and End.
Implementation Notes
- Renders a
<div> with role="scrollbar" and full ARIA scrollbar attributes
- Supports
"vertical" and "horizontal" orientations via aria-orientation
- Includes
aria-valuenow, aria-valuemin, and aria-valuemax for position tracking
- Initial values are set to 0/0/100; consumer should update these dynamically
- The
label prop provides the accessible name via aria-label
- Consumer provides the scrollbar thumb or track content via the
children slot
- Rest props are spread onto the
<div> element
Related components
scroll-area — a scrollable container with custom scrollbar support
References
- WAI-ARIA scrollbar role: https://www.w3.org/TR/wai-aria-1.2/#scrollbar
- WAI-ARIA Practices - ScrollBar: https://www.w3.org/WAI/ARIA/apg/patterns/scrollbar/
Canonical contract
Generated from this component's canonical metadata — the machine-checked source the implementations are held to.
Metadata
- Component: scroll-bar
- PascalCase: ScrollBar
- Description: a custom scrollbar element
- Status: beta — implemented and unit-tested in all seven frameworks with an axe-clean demo page; not yet exercised in composed flows
- HTML tag: <div>
- CSS class: .scroll-bar
- Interactive: yes
ARIA
role="scrollbar" -- identifies the element as a scrollbar control aria-label="..." -- provides the accessible name for the scrollbar aria-orientation="vertical|horizontal" -- indicates the scrollbar direction aria-valuenow="0" -- the current scroll position (consumer should update dynamically) aria-valuemin="0" -- the minimum scroll value aria-valuemax="100" -- the maximum scroll value
Keyboard
- Arrow Up / Arrow Left: Scroll backward (decrease value) by a small increment
- Arrow Down / Arrow Right: Scroll forward (increase value) by a small increment
- Page Up: Scroll backward by a large increment
- Page Down: Scroll forward by a large increment
- Home: Scroll to the beginning (minimum value)
- End: Scroll to the end (maximum value)
Props
orientation: "vertical" | "horizontal" (default: "vertical") -- the scrollbar direction, reflected in aria-orientation label: string (required) -- accessible name for the scrollbar via aria-label children: slot (required) -- scrollbar content, typically the draggable thumb element ...restProps: unknown -- additional attributes spread onto the <div> element