Scroll Area
A scrollable region with a thin, themed native scrollbar.
import { … } from '@inlaylab/ivorie/scroll-area'import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IV_SCROLL_AREA_IMPORTS } from '@inlaylab/ivorie/scroll-area';
@Component({
selector: 'demo-scroll-area',
imports: [IV_SCROLL_AREA_IMPORTS],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<iv-scroll-area maxHeight="240px" class="w-64 rounded-md border">
@for (item of items; track item) {
<div class="border-b px-3 py-2 text-sm last:border-b-0">{{ item }}</div>
}
</iv-scroll-area>
`,
})
export default class ScrollAreaDemo {
protected readonly items = Array.from({ length: 30 }, (_, i) => `Item ${i + 1}`);
}
Installation
npx ivorie add scroll-areaimport { … } from '@inlaylab/ivorie/scroll-area'Ports the shadcn/ui ScrollArea. It uses the browser's native scrolling and styles the scrollbar with CSS. No measuring, so it works with SSR.
Usage
import { IV_SCROLL_AREA_IMPORTS } from '@inlaylab/ivorie/scroll-area';<iv-scroll-area maxHeight="300px">
<div class="px-3 py-2 text-sm">Long content</div>
</iv-scroll-area>Examples
Horizontal
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IV_SCROLL_AREA_IMPORTS } from '@inlaylab/ivorie/scroll-area';
@Component({
selector: 'demo-scroll-area-horizontal',
imports: [IV_SCROLL_AREA_IMPORTS],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<iv-scroll-area type="scroll-x" class="w-80 rounded-md border">
<div class="flex w-max gap-3 p-3">
@for (col of columns; track col) {
<div class="flex h-20 w-32 shrink-0 items-center justify-center rounded-md bg-muted text-sm">{{ col }}</div>
}
</div>
</iv-scroll-area>
`,
})
export default class ScrollAreaHorizontalDemo {
protected readonly columns = Array.from({ length: 12 }, (_, i) => `Card ${i + 1}`);
}
Both axes
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IV_SCROLL_AREA_IMPORTS } from '@inlaylab/ivorie/scroll-area';
@Component({
selector: 'demo-scroll-area-both-axes',
imports: [IV_SCROLL_AREA_IMPORTS],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<iv-scroll-area type="always" maxHeight="200px" maxWidth="320px" class="rounded-md border">
<div class="grid w-[640px] grid-cols-4 gap-2 p-3 text-sm">
@for (cell of cells; track cell) {
<div class="rounded-md bg-muted p-3">{{ cell }}</div>
}
</div>
</iv-scroll-area>
`,
})
export default class ScrollAreaBothAxesDemo {
protected readonly cells = Array.from({ length: 24 }, (_, i) => `Cell ${i + 1}`);
}
Fill parent
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IV_SCROLL_AREA_IMPORTS } from '@inlaylab/ivorie/scroll-area';
@Component({
selector: 'demo-scroll-area-fill-parent',
imports: [IV_SCROLL_AREA_IMPORTS],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div class="h-56 w-64">
<iv-scroll-area class="h-full rounded-md border">
@for (item of items; track item) {
<div class="px-3 py-2 text-sm">{{ item }}</div>
}
</iv-scroll-area>
</div>
`,
})
export default class ScrollAreaFillParentDemo {
protected readonly items = Array.from({ length: 30 }, (_, i) => `Item ${i + 1}`);
}
API
Every part also accepts class.
iv-scroll-area
| Name | Type | Default | Description |
|---|---|---|---|
type |
'auto' | 'always' | 'scroll-x' | 'scroll-y' |
'auto' |
auto: scrollbars when content overflows. always: scrollbars always shown. scroll-x: horizontal only. scroll-y: vertical only. |
maxHeight |
string |
'' |
CSS max-height of the viewport, for example '300px' or '50vh'. |
maxWidth |
string |
'' |
CSS max-width of the viewport. |
Accessibility
- The viewport has
tabindex="0", so keyboard users can focus it and scroll with the arrow, Page and Home/End keys. - A focus ring shows on
:focus-visible.
Notes
classgoes on the host. The viewport fills the host (size-full) and inherits its border radius, so setrounded-*on the host.- For a fixed height, set
maxHeightor add anh-*class to the host. - The scrollbar is 10px, with a transparent track and a
--bordercolored thumb. Firefox usesscrollbar-width: thin. - Styles target the
.iv-scroll-area-viewportclass only. They do not affect other scrollable elements.