Skip to main content

upp-scrollable

A scroll container component that provides configurable scroll behavior for its content. It supports horizontal scrolling, vertical scrolling, both directions, or no scrolling at all. CSS classes are applied dynamically based on the selected direction, and it integrates with viewService for viewport-aware adjustments.

When to Use

Use upp-scrollable to wrap content that may overflow its container and needs controlled scroll behavior. It is particularly useful inside upp-panel-content or any fixed-height container where you want explicit control over which scroll directions are enabled.

Demo

Source Code

<h2>upp-scrollable</h2>
<p class="demo-description">Message feed with configurable scroll direction via <code>upp-scrollable</code>.</p>

<div class="demo-controls">
<span class="control-label">Direction:</span>
<ion-button size="small" [fill]="direction === 'none' ? 'solid' : 'outline'" (click)="setDirection('none')">none</ion-button>
<ion-button size="small" [fill]="direction === 'x' ? 'solid' : 'outline'" (click)="setDirection('x')">x</ion-button>
<ion-button size="small" [fill]="direction === 'y' ? 'solid' : 'outline'" (click)="setDirection('y')">y</ion-button>
<ion-button size="small" [fill]="direction === 'both' ? 'solid' : 'outline'" (click)="setDirection('both')">both</ion-button>
</div>

<div class="demo-section">
<h3>Messages (scrollbar={{ direction }})</h3>
<div class="feed-container">
<upp-scrollable [scrollbar]="direction">
<div [class]="direction === 'x' ? 'messages-row' : 'messages-column'">
<div class="message-card" *ngFor="let msg of messages">
<div class="message-header">
<span class="message-sender">{{ msg.sender }}</span>
<span class="message-time">{{ msg.time }}</span>
</div>
<div class="message-text">{{ msg.text }}</div>
</div>
</div>
</upp-scrollable>
</div>
</div>

API Reference

upp-scrollable

PropertyTypeDefaultDescription
scrollbar'none' | 'x' | 'y' | 'both''none'Controls which scroll directions are enabled. 'none' hides all scrollbars, 'x' enables horizontal only, 'y' enables vertical only, and 'both' enables both directions.

Horizontal (scrollbar="x"): the host keeps content height (height: auto) and does not grow to fill a column-flex parent, so it fits slim rows (e.g. under upp-panel-header). --upp-scrollable-bottom-gap defaults to 0px in this mode; set it on the host if you still need trailing space.

CSS (host): --upp-scrollable-max-height — optional; when set by a parent (e.g. upp-select on the list’s upp-scrollable), the host uses it as max-height so content taller than the cap scrolls inside .upp-scrollable-content. Use a length or var(--your-token).

The trailing spacer after projected content uses --upp-scrollable-bottom-gap (default 200px for y / both / none, class .bottom-gap). Ancestors can override it (for example upp-select sets 0px on the list’s upp-scrollable).

The component dynamically applies CSS classes based on the scrollbar value:

scrollbar valueCSS classes applied
'none'--no-scrollbar-x --no-scrollbar-y
'x'--no-scrollbar-y --scroll-x-only
'y'--no-scrollbar-x
'both'(none)