Skip to content
Ndop UI

Scroll Area

A scrollable region with styled scrollbars.

  • v1.0.0
  • SSR
  • Zoneless
  • 0.6 kB gzip

Tags

v1.2.0-beta.30
v1.2.0-beta.29
v1.2.0-beta.28
v1.2.0-beta.27
v1.2.0-beta.26
v1.2.0-beta.25
v1.2.0-beta.24
v1.2.0-beta.23
v1.2.0-beta.22
v1.2.0-beta.21
v1.2.0-beta.20
v1.2.0-beta.19
v1.2.0-beta.18
v1.2.0-beta.17
v1.2.0-beta.16
v1.2.0-beta.15
v1.2.0-beta.14
v1.2.0-beta.13
v1.2.0-beta.12
v1.2.0-beta.11
v1.2.0-beta.10
v1.2.0-beta.9
v1.2.0-beta.8
v1.2.0-beta.7
v1.2.0-beta.6
v1.2.0-beta.5
v1.2.0-beta.4
v1.2.0-beta.3
v1.2.0-beta.2
v1.2.0-beta.1
import { Component } from '@angular/core';
import { ScrollArea } from '@/ui/scroll-area/scroll-area';
import { Separator } from '@/ui/separator/separator';

/** A list of tags that scrolls vertically in a fixed height. */
@Component({
  selector: 'example-scroll-area-demo',
  imports: [ScrollArea, Separator],
  template: `
    <div ndScrollArea class="h-72 w-48 rounded-md border" aria-label="Tags">
      <div class="p-4">
        <h2 class="mb-4 text-sm leading-none font-medium">Tags</h2>
        @for (tag of tags; track tag; let last = $last) {
          <div class="text-sm">{{ tag }}</div>
          @if (!last) {
            <div ndSeparator decorative class="my-2"></div>
          }
        }
      </div>
    </div>
  `,
})
export class ScrollAreaDemoExample {
  protected readonly tags = Array.from(
    { length: 30 },
    (_, index) => `v1.2.0-beta.${30 - index}`,
  );
}

Scroll Area is a region that scrolls inside a fixed size, with thin scrollbars in the theme's border color. It uses the browser's own scrolling, so touch, the mouse wheel and the keyboard all work, and it can take focus so keyboard users can scroll it with the arrow keys. Choose vertical, horizontal or both.

Installation

npx @ndop/cli add scroll-area

Usage

import { ScrollArea } from '@/ui/scroll-area/scroll-area';
import { Separator } from '@/ui/separator/separator';
<div ndScrollArea class="h-72 w-48 rounded-md border" aria-label="Tags">
  <div class="p-4">
    <h2 class="mb-4 text-sm leading-none font-medium">Tags</h2>
    @for (tag of tags; track tag; let last = $last) {
      <div class="text-sm">{{ tag }}</div>
      @if (!last) {
        <div ndSeparator decorative class="my-2"></div>
      }
    }
  </div>
</div>

Examples

Scroll Area horizontal

A row of artworks that scrolls sideways.

  • By Ornella Binni
  • By Tom Byrom
  • By Vladimir Malyavko
  • By Ahmed Saeed
import { Component } from '@angular/core';
import { AspectRatio } from '@/ui/aspect-ratio/aspect-ratio';
import { ScrollArea } from '@/ui/scroll-area/scroll-area';

/** A row of artworks that scrolls sideways. */
@Component({
  selector: 'example-scroll-area-horizontal',
  imports: [AspectRatio, ScrollArea],
  template: `
    <div
      ndScrollArea
      orientation="horizontal"
      class="w-full max-w-md rounded-md border whitespace-nowrap"
      aria-label="Artworks"
    >
      <ul class="flex w-max gap-4 p-4">
        @for (artwork of artworks; track artwork.title) {
          <li class="w-36 shrink-0">
            <figure>
              <div
                ndAspectRatio
                [ratio]="3 / 4"
                class="rounded-md bg-muted"
              ></div>
              <figcaption class="pt-2 text-xs text-muted-foreground">
                By
                <span class="font-semibold text-foreground">{{
                  artwork.artist
                }}</span>
              </figcaption>
            </figure>
          </li>
        }
      </ul>
    </div>
  `,
})
export class ScrollAreaHorizontalExample {
  protected readonly artworks = [
    { title: 'Ripple', artist: 'Ornella Binni' },
    { title: 'Stillness', artist: 'Tom Byrom' },
    { title: 'Drift', artist: 'Vladimir Malyavko' },
    { title: 'Haze', artist: 'Ahmed Saeed' },
  ];
}

Accessibility

Scroll Area has no keyboard interaction or focus handling of its own; it keeps the semantics of the element it's on.

API reference

ScrollArea

[ndScrollArea]

A scrollable region with thin, themed scrollbars, using the browser's own scrolling (ADR-0021): touch, wheel and keyboard scrolling all work, and it can take focus, so keyboard users can scroll it. Give it a size and, when it holds more than a list, a name with aria-label.

ScrollArea binding Type Default
[orientation]
Which way it scrolls.
'horizontal' | 'vertical' | 'both''vertical'
[class]
Extra classes, merged last so they win.
string''
Data attribute Values
data-slotscroll-area
data-orientation —

Agent notes

Do

  • Give it a height (or width, when horizontal), such as class="h-72".
  • Name it with aria-label when it holds a section of the page rather than a single list.
  • Keep focusable controls inside it reachable; scrolling follows focus.

Don't

  • Don't nest scroll areas in the same direction.
  • Don't use it to hide content that should be visible; let the page scroll.