Scroller
A horizontal scroll container with gradient fade indicators. Ideal for tab bars, tag lists, and other content that may overflow its container.
Tag list
Wrap a horizontal list of tags in a scroller. Gradient fades and scroll buttons appear automatically when the content overflows. Scroll buttons disappear at either edge once fully scrolled.
<diwa-scroller>
<div style='{"display":"flex","gap":"12px","padding":"12px 4px"}'>
<diwa-tag variant="neutral">React</diwa-tag>
<diwa-tag variant="neutral">TypeScript</diwa-tag>
<diwa-tag variant="neutral">Stencil</diwa-tag>
<diwa-tag variant="neutral">Design System</diwa-tag>
<diwa-tag variant="neutral">Web Components</diwa-tag>
<diwa-tag variant="neutral">CSS Custom Properties</diwa-tag>
<diwa-tag variant="neutral">Accessibility</diwa-tag>
<diwa-tag variant="neutral">Dark Mode</diwa-tag>
<diwa-tag variant="neutral">Design Tokens</diwa-tag>
<diwa-tag variant="neutral">Shadow DOM</diwa-tag>
<diwa-tag variant="neutral">Slots</diwa-tag>
<diwa-tag variant="neutral">Custom Events</diwa-tag>
<diwa-tag variant="neutral">Theming</diwa-tag>
<diwa-tag variant="neutral">Server-Side Rendering</diwa-tag>
<diwa-tag variant="neutral">Progressive Enhancement</diwa-tag>
</div>
</diwa-scroller>Card row
Use the scroller for horizontally browsable card groups — product listings, feature highlights, team members, or media thumbnails. Cards are fixed-width and scroll naturally with the gradient fade indicators.
Design Tokens
CSS custom properties for consistent theming
Components
Reusable UI building blocks with a unified API
Accessibility
WCAG 2.1 compliant out of the box
Dark Mode
First-class dark theme support built in
TypeScript
Fully typed API surface across all frameworks
Web Standards
Native custom elements with Shadow DOM
Framework Agnostic
Works with React, Angular, Vue, and vanilla JS
Motion Safe
Respects prefers-reduced-motion globally
<diwa-scroller>
<div style='{"display":"flex","gap":"16px","padding":"16px 4px"}'>
<div style='{"width":"180px","flexShrink":0,"background":"var(--diwa-bg-elevated)","border":"1px solid var(--diwa-border)","borderRadius":"8px","padding":"16px","boxSizing":"border-box"}'>
<p style='{"margin":"0 0 6px","fontWeight":"600","fontSize":"13px","color":"var(--diwa-text-primary)","lineHeight":"1.3"}'>Design Tokens</p>
<p style='{"margin":"0","fontSize":"12px","color":"var(--diwa-text-secondary)","lineHeight":"1.5"}'>CSS custom properties for consistent theming</p>
</div>
<div style='{"width":"180px","flexShrink":0,"background":"var(--diwa-bg-elevated)","border":"1px solid var(--diwa-border)","borderRadius":"8px","padding":"16px","boxSizing":"border-box"}'>
<p style='{"margin":"0 0 6px","fontWeight":"600","fontSize":"13px","color":"var(--diwa-text-primary)","lineHeight":"1.3"}'>Components</p>
<p style='{"margin":"0","fontSize":"12px","color":"var(--diwa-text-secondary)","lineHeight":"1.5"}'>Reusable UI building blocks with a unified API</p>
</div>
<div style='{"width":"180px","flexShrink":0,"background":"var(--diwa-bg-elevated)","border":"1px solid var(--diwa-border)","borderRadius":"8px","padding":"16px","boxSizing":"border-box"}'>
<p style='{"margin":"0 0 6px","fontWeight":"600","fontSize":"13px","color":"var(--diwa-text-primary)","lineHeight":"1.3"}'>Accessibility</p>
<p style='{"margin":"0","fontSize":"12px","color":"var(--diwa-text-secondary)","lineHeight":"1.5"}'>WCAG 2.1 compliant out of the box</p>
</div>
<div style='{"width":"180px","flexShrink":0,"background":"var(--diwa-bg-elevated)","border":"1px solid var(--diwa-border)","borderRadius":"8px","padding":"16px","boxSizing":"border-box"}'>
<p style='{"margin":"0 0 6px","fontWeight":"600","fontSize":"13px","color":"var(--diwa-text-primary)","lineHeight":"1.3"}'>Dark Mode</p>
<p style='{"margin":"0","fontSize":"12px","color":"var(--diwa-text-secondary)","lineHeight":"1.5"}'>First-class dark theme support built in</p>
</div>
<div style='{"width":"180px","flexShrink":0,"background":"var(--diwa-bg-elevated)","border":"1px solid var(--diwa-border)","borderRadius":"8px","padding":"16px","boxSizing":"border-box"}'>
<p style='{"margin":"0 0 6px","fontWeight":"600","fontSize":"13px","color":"var(--diwa-text-primary)","lineHeight":"1.3"}'>TypeScript</p>
<p style='{"margin":"0","fontSize":"12px","color":"var(--diwa-text-secondary)","lineHeight":"1.5"}'>Fully typed API surface across all frameworks</p>
</div>
<div style='{"width":"180px","flexShrink":0,"background":"var(--diwa-bg-elevated)","border":"1px solid var(--diwa-border)","borderRadius":"8px","padding":"16px","boxSizing":"border-box"}'>
<p style='{"margin":"0 0 6px","fontWeight":"600","fontSize":"13px","color":"var(--diwa-text-primary)","lineHeight":"1.3"}'>Web Standards</p>
<p style='{"margin":"0","fontSize":"12px","color":"var(--diwa-text-secondary)","lineHeight":"1.5"}'>Native custom elements with Shadow DOM</p>
</div>
<div style='{"width":"180px","flexShrink":0,"background":"var(--diwa-bg-elevated)","border":"1px solid var(--diwa-border)","borderRadius":"8px","padding":"16px","boxSizing":"border-box"}'>
<p style='{"margin":"0 0 6px","fontWeight":"600","fontSize":"13px","color":"var(--diwa-text-primary)","lineHeight":"1.3"}'>Framework Agnostic</p>
<p style='{"margin":"0","fontSize":"12px","color":"var(--diwa-text-secondary)","lineHeight":"1.5"}'>Works with React, Angular, Vue, and vanilla JS</p>
</div>
<div style='{"width":"180px","flexShrink":0,"background":"var(--diwa-bg-elevated)","border":"1px solid var(--diwa-border)","borderRadius":"8px","padding":"16px","boxSizing":"border-box"}'>
<p style='{"margin":"0 0 6px","fontWeight":"600","fontSize":"13px","color":"var(--diwa-text-primary)","lineHeight":"1.3"}'>Motion Safe</p>
<p style='{"margin":"0","fontSize":"12px","color":"var(--diwa-text-secondary)","lineHeight":"1.5"}'>Respects prefers-reduced-motion globally</p>
</div>
</div>
</diwa-scroller>With scrollbar visible
Set scrollbar to show the native horizontal scrollbar alongside the gradient indicators. Useful in data-dense UIs where users expect a visible scroll handle.
<diwa-scroller scrollbar>
<div style='{"display":"flex","gap":"12px","padding":"12px 4px"}'>
<diwa-tag variant="primary">React</diwa-tag>
<diwa-tag variant="primary">TypeScript</diwa-tag>
<diwa-tag variant="primary">Stencil</diwa-tag>
<diwa-tag variant="primary">Design System</diwa-tag>
<diwa-tag variant="primary">Web Components</diwa-tag>
<diwa-tag variant="primary">CSS Custom Properties</diwa-tag>
<diwa-tag variant="primary">Accessibility</diwa-tag>
<diwa-tag variant="primary">Dark Mode</diwa-tag>
<diwa-tag variant="primary">Design Tokens</diwa-tag>
<diwa-tag variant="primary">Shadow DOM</diwa-tag>
<diwa-tag variant="primary">Slots</diwa-tag>
<diwa-tag variant="primary">Custom Events</diwa-tag>
<diwa-tag variant="primary">Theming</diwa-tag>
<diwa-tag variant="primary">Server-Side Rendering</diwa-tag>
<diwa-tag variant="primary">Progressive Enhancement</diwa-tag>
</div>
</diwa-scroller>Scroll indicator alignment
Use alignScrollIndicator to position the gradient fades and scroll buttons relative to the scroll area — useful when the scroller sits inside a taller container.
top
<diwa-scroller align-scroll-indicator="top">
<div style='{"display":"flex","gap":"12px","padding":"12px 4px"}'>
<diwa-tag variant="neutral">React</diwa-tag>
<diwa-tag variant="neutral">TypeScript</diwa-tag>
<diwa-tag variant="neutral">Stencil</diwa-tag>
<diwa-tag variant="neutral">Design System</diwa-tag>
<diwa-tag variant="neutral">Web Components</diwa-tag>
<diwa-tag variant="neutral">CSS Custom Properties</diwa-tag>
<diwa-tag variant="neutral">Accessibility</diwa-tag>
<diwa-tag variant="neutral">Dark Mode</diwa-tag>
<diwa-tag variant="neutral">Design Tokens</diwa-tag>
<diwa-tag variant="neutral">Shadow DOM</diwa-tag>
<diwa-tag variant="neutral">Slots</diwa-tag>
<diwa-tag variant="neutral">Custom Events</diwa-tag>
<diwa-tag variant="neutral">Theming</diwa-tag>
<diwa-tag variant="neutral">Server-Side Rendering</diwa-tag>
<diwa-tag variant="neutral">Progressive Enhancement</diwa-tag>
</div>
</diwa-scroller>center (default)
<diwa-scroller align-scroll-indicator="center">
<div style='{"display":"flex","gap":"12px","padding":"12px 4px"}'>
<diwa-tag variant="neutral">React</diwa-tag>
<diwa-tag variant="neutral">TypeScript</diwa-tag>
<diwa-tag variant="neutral">Stencil</diwa-tag>
<diwa-tag variant="neutral">Design System</diwa-tag>
<diwa-tag variant="neutral">Web Components</diwa-tag>
<diwa-tag variant="neutral">CSS Custom Properties</diwa-tag>
<diwa-tag variant="neutral">Accessibility</diwa-tag>
<diwa-tag variant="neutral">Dark Mode</diwa-tag>
<diwa-tag variant="neutral">Design Tokens</diwa-tag>
<diwa-tag variant="neutral">Shadow DOM</diwa-tag>
<diwa-tag variant="neutral">Slots</diwa-tag>
<diwa-tag variant="neutral">Custom Events</diwa-tag>
<diwa-tag variant="neutral">Theming</diwa-tag>
<diwa-tag variant="neutral">Server-Side Rendering</diwa-tag>
<diwa-tag variant="neutral">Progressive Enhancement</diwa-tag>
</div>
</diwa-scroller>bottom
<diwa-scroller align-scroll-indicator="bottom">
<div style='{"display":"flex","gap":"12px","padding":"12px 4px"}'>
<diwa-tag variant="neutral">React</diwa-tag>
<diwa-tag variant="neutral">TypeScript</diwa-tag>
<diwa-tag variant="neutral">Stencil</diwa-tag>
<diwa-tag variant="neutral">Design System</diwa-tag>
<diwa-tag variant="neutral">Web Components</diwa-tag>
<diwa-tag variant="neutral">CSS Custom Properties</diwa-tag>
<diwa-tag variant="neutral">Accessibility</diwa-tag>
<diwa-tag variant="neutral">Dark Mode</diwa-tag>
<diwa-tag variant="neutral">Design Tokens</diwa-tag>
<diwa-tag variant="neutral">Shadow DOM</diwa-tag>
<diwa-tag variant="neutral">Slots</diwa-tag>
<diwa-tag variant="neutral">Custom Events</diwa-tag>
<diwa-tag variant="neutral">Theming</diwa-tag>
<diwa-tag variant="neutral">Server-Side Rendering</diwa-tag>
<diwa-tag variant="neutral">Progressive Enhancement</diwa-tag>
</div>
</diwa-scroller>Dynamic content
The scroller recalculates overflow whenever its content changes. Filter the tags below to see scroll buttons and gradient fades appear and disappear automatically.