# Scrollbar

- Entry point: `@koobiq/components/scrollbar`
- Page: https://koobiq.io/en/components/scrollbar/overview

## Overview

`KbqScrollbar` is a customizable scrollbar. It can remain visible, appear on hover or while scrolling, or stay hidden. The component supports mouse wheel, touch gestures, and keyboard controls and provides methods for programmatic scrolling.

### Display mode

The `kbqScrollbarMode` input sets the display mode:

| Mode     | Description                                                           |
| -------- | --------------------------------------------------------------------- |
| `hover`  | Appears on pointer hover or while scrolling. This is the default mode |
| `always` | Remains visible while the content overflows                           |
| `native` | Displays the browser's native scrollbar                               |
| `hidden` | Remains hidden while the content can still be scrolled                |

In `hover` and `always` modes a bar is drawn only for an axis the user can scroll: an axis whose computed `overflow` is `hidden`, `clip` or `visible` gets no bar, however far its content overflows.

`kbqScrollbarOptionsProvider` sets the default mode for the entire application or a specific injector.

**Example: Scrollbar overview example** (`scrollbar-overview`)

```ts scrollbar-overview-example.ts
import { ChangeDetectionStrategy, Component, model } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { KbqScrollbar, KbqScrollbarMode } from '@koobiq/components/scrollbar';
import { KbqSelectModule } from '@koobiq/components/select';

@Component({
    selector: 'scrollbar-overview-example',
    imports: [KbqScrollbar, KbqSelectModule, FormsModule],
    template: `
        <kbq-form-field class="example-form-field">
            <kbq-select [(ngModel)]="mode">
                @for (mode of modes; track mode) {
                    <kbq-option [value]="mode">{{ mode }}</kbq-option>
                }
            </kbq-select>
        </kbq-form-field>

        <div class="example-scrollbar-wrapper">
            <kbq-scrollbar class="example-scrollbar" [kbqScrollbarMode]="mode()">
                <p>
                    In cryptography, a brute-force attack or exhaustive key search is a cryptanalytic attack that
                    consists of an attacker submitting many possible keys or passwords with the hope of eventually
                    guessing correctly. This strategy can theoretically be used to break any form of encryption that is
                    not information-theoretically secure.[1] However, in a properly designed cryptosystem the chance of
                    successfully guessing the key is negligible.
                </p>
                <p>
                    Brute-force attacks are an application of brute-force search, the general problem-solving technique
                    of enumerating all candidates and checking each one. The word 'hammering' is sometimes used to
                    describe a brute-force attack,[4] with 'anti-hammering' for countermeasures.[5]
                </p>
                <p>
                    When cracking passwords, this method is very fast when used to check all short passwords, but for
                    longer passwords other methods such as the dictionary attack are used because a brute-force search
                    takes too long. Longer passwords, passphrases and keys have more possible values, making them
                    exponentially more difficult to crack than shorter ones due to the diversity of characters.[2]
                </p>
                <p>
                    Brute-force attacks can be made less effective by implementing key stretching techniques making it
                    more difficult for an attacker to recognize when the code has been cracked or by making the attacker
                    do more work to test each guess. One of the measures of the strength of an encryption system is how
                    long it would theoretically take an attacker to mount a successful brute-force attack against it.[3]
                </p>
                <p>
                    When cracking passwords, this method is very fast when used to check all short passwords, but for
                    longer passwords other methods such as the dictionary attack are used because a brute-force search
                    takes too long. Longer passwords, passphrases and keys have more possible values, making them
                    exponentially more difficult to crack than shorter ones due to the diversity of characters.[2]
                </p>
                <p>
                    Brute-force attacks are an application of brute-force search, the general problem-solving technique
                    of enumerating all candidates and checking each one. The word 'hammering' is sometimes used to
                    describe a brute-force attack,[4] with 'anti-hammering' for countermeasures.[5]
                </p>
            </kbq-scrollbar>
        </div>
    `,
    styles: `
        :host {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: var(--kbq-size-l);
            padding: var(--kbq-size-l);
        }

        .example-form-field {
            width: 200px;
        }

        .example-scrollbar-wrapper {
            overflow: hidden;
            resize: both;
            width: 100%;
            max-width: 100%;
            min-width: 200px;
            height: 200px;
            max-height: 400px;
            min-height: 200px;
        }

        .example-scrollbar {
            height: 100%;
            width: 100%;
            border-radius: var(--kbq-size-border-radius);
            background-color: var(--kbq-background-bg-secondary);
            outline-offset: -1px;
        }

        p {
            width: 150%;
            margin: var(--kbq-size-l);
        }
    `,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class ScrollbarOverviewExample {
    protected readonly modes: KbqScrollbarMode[] = ['hover', 'always', 'native', 'hidden'] as const;
    protected readonly mode = model<KbqScrollbarMode>('hover');
}
```

### Virtual scrolling

Apply the `kbqScrollbarViewport` directive to `cdk-virtual-scroll-viewport` to add a customizable scrollbar. The directive supports the same display modes.

**Example: Scrollbar with virtual scroll** (`scrollbar-virtual-scroll`)

```ts scrollbar-virtual-scroll-example.ts
import { ScrollingModule } from '@angular/cdk/scrolling';
import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import { KbqButtonModule } from '@koobiq/components/button';
import { KbqScrollbarViewport } from '@koobiq/components/scrollbar';

@Component({
    selector: 'scrollbar-virtual-scroll-example',
    imports: [KbqScrollbarViewport, ScrollingModule, KbqButtonModule],
    template: `
        <button kbq-button (click)="addItems()">Add items</button>

        <cdk-virtual-scroll-viewport kbqScrollbarViewport class="example-scrollbar" itemSize="32">
            <div *cdkVirtualFor="let item of items()" class="example-item">{{ item }}</div>
        </cdk-virtual-scroll-viewport>
    `,
    styles: `
        :host {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: var(--kbq-size-l);
            padding: var(--kbq-size-l);
        }

        .example-scrollbar {
            height: 320px;
            width: 320px;
            border-radius: var(--kbq-size-border-radius);
            background-color: var(--kbq-background-bg-secondary);
        }

        .example-item {
            padding: 0 var(--kbq-size-s);
            line-height: 32px;
            height: 32px;
        }
    `,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class ScrollbarVirtualScrollExample {
    protected readonly items = signal(Array.from({ length: 100 }).map((_, i) => `Item #${i}`));

    protected addItems(): void {
        const nextIndex = this.items().length;
        const newItems = Array.from({ length: 100 }).map((_, i) => `Item #${nextIndex + i}`);

        this.items.update((items) => [...items, ...newItems]);
    }
}
```

### Programmatic scrolling

Access the component instance through the `kbqScrollbar` export and call one of its public methods:

| Method                             | Description                                                                            |
| ---------------------------------- | -------------------------------------------------------------------------------------- |
| `scrollTo`                         | Scrolls to the specified coordinates                                                   |
| `scrollToTop` and `scrollToBottom` | Scroll to the top or bottom edge                                                       |
| `scrollStart` and `scrollEnd`      | Scroll to the logical start or end horizontally, respecting RTL                        |
| `scrollToElement`                  | Scrolls to an element specified directly or by a CSS selector. Supports custom offsets |
| `scrollIntoView`                   | Centers an element within the viewport                                                 |

The `behavior` parameter accepts `auto`, `instant`, and `smooth`.

**Example: Scrollbar scrollTo methods** (`scrollbar-scroll-to`)

```ts scrollbar-scroll-to-example.ts
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { KbqButtonModule } from '@koobiq/components/button';
import { KbqScrollbar } from '@koobiq/components/scrollbar';

@Component({
    selector: 'scrollbar-scroll-to-example',
    imports: [KbqScrollbar, KbqButtonModule],
    template: `
        <div class="example-buttons">
            <button kbq-button (click)="scrollbar.scrollToTop('smooth')">Scroll top</button>
            <button kbq-button (click)="scrollbar.scrollToBottom('smooth')">Scroll bottom</button>
            <button kbq-button (click)="scrollbar.scrollStart('smooth')">Scroll start</button>
            <button kbq-button (click)="scrollbar.scrollEnd('smooth')">Scroll end</button>
            <button
                kbq-button
                (click)="scrollbar.scrollToElement(scrollToElementTarget, { behavior: 'smooth', top: 16, left: 16 })"
            >
                Scroll to element
            </button>
            <button kbq-button (click)="scrollbar.scrollIntoView(scrollIntoViewTarget, 'smooth')">
                Scroll into view
            </button>
        </div>

        <kbq-scrollbar #scrollbar="kbqScrollbar" class="example-scrollbar">
            <p>
                In cryptography, a brute-force attack or exhaustive key search is a cryptanalytic attack that consists
                of an attacker submitting many possible keys or passwords with the hope of eventually guessing
                correctly. This strategy can theoretically be used to break any form of encryption that is not
                information-theoretically secure.[1] However, in a properly designed cryptosystem the chance of
                successfully guessing the key is negligible.
            </p>
            <p>
                Brute-force attacks can be made less effective by implementing key stretching techniques making it more
                difficult for an attacker to recognize when the code has been cracked or by making the attacker do more
                work to test each guess. One of the measures of the strength of an encryption system is how long it
                would theoretically take an attacker to mount a successful brute-force attack against it.[3]
            </p>
            <p>
                Brute-force attacks can be made less effective by implementing key stretching techniques making it more
                difficult for an attacker to recognize when the code has been cracked or by making the attacker do more
                work to test each guess. One of the measures of the strength of an encryption system is how long it
                would theoretically take an attacker to mount a successful brute-force attack against it.[3]
            </p>
            <p>
                Brute-force attacks can be made less effective by implementing key stretching techniques making it more
                difficult for an attacker to recognize when the code has been cracked or by making the attacker do more
                work to test each guess. One of the measures of the strength of an encryption system is how long it
                would theoretically take an attacker to mount a successful brute-force attack against it.[3]
            </p>
            <p>
                <b #scrollToElementTarget>[SCROLL TO ELEMENT]</b>
                When cracking passwords, this method is very fast when used to check all short passwords, but for longer
                passwords other methods such as the dictionary attack are used because a brute-force search takes too
                long. Longer passwords, passphrases and keys have more possible values, making them exponentially more
                difficult to crack than shorter ones due to the diversity of characters.[2]
            </p>
            <p>
                Brute-force attacks can be made less effective by implementing key stretching techniques making it more
                difficult for an attacker to recognize when
                <b #scrollIntoViewTarget>[SCROLL INTO VIEW]</b>
                the code has been cracked or by making the attacker do more work to test each guess. One of the measures
                of the strength of an encryption system is how long it would theoretically take an attacker to mount a
                successful brute-force attack against it.[3]
            </p>
            <p>
                Brute-force attacks can be made less effective by implementing key stretching techniques making it more
                difficult for an attacker to recognize when the code has been cracked or by making the attacker do more
                work to test each guess. One of the measures of the strength of an encryption system is how long it
                would theoretically take an attacker to mount a successful brute-force attack against it.[3]
            </p>
            <p>
                Brute-force attacks can be made less effective by implementing key stretching techniques making it more
                difficult for an attacker to recognize when the code has been cracked or by making the attacker do more
                work to test each guess. One of the measures of the strength of an encryption system is how long it
                would theoretically take an attacker to mount a successful brute-force attack against it.[3]
            </p>
            <p>
                In cryptography, a brute-force attack or exhaustive key search is a cryptanalytic attack that consists
                of an attacker submitting many possible keys or passwords with the hope of eventually guessing
                correctly. This strategy can theoretically be used to break any form of encryption that is not
                information-theoretically secure.[1] However, in a properly designed cryptosystem the chance of
                successfully guessing the key is negligible.
            </p>
        </kbq-scrollbar>
    `,
    styles: `
        :host {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: var(--kbq-size-l);
            padding: var(--kbq-size-l);
        }

        .example-buttons {
            display: flex;
            flex-wrap: wrap;
            gap: var(--kbq-size-s);
        }

        .example-scrollbar {
            max-height: 200px;
            width: 100%;
            border-radius: var(--kbq-size-border-radius);
            background-color: var(--kbq-background-bg-secondary);
        }

        p {
            width: 150%;
            margin: var(--kbq-size-l);
        }
    `,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class ScrollbarScrollToExample {}
```

### Scroll indicator

Call `flashScrollIndicators` to briefly reveal the scrollbar and indicate that scrolling is available:

```ts
import { afterNextRender, ChangeDetectionStrategy, Component, viewChild } from '@angular/core';
import { KbqScrollbar } from '@koobiq/components/scrollbar';

@Component({
    imports: [KbqScrollbar],
    template: `
        <kbq-scrollbar>...</kbq-scrollbar>
    `,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class FlashScrollIndicatorsExample {
    private readonly scrollbar = viewChild.required(KbqScrollbar);

    constructor() {
        afterNextRender(() => {
            this.scrollbar().flashScrollIndicators();
        });
    }
}
```

### Browser scrollbar

The `kbqNativeScrollbar` directive customizes an element's scrollbar without replacing the browser's scrolling mechanism. Add `kbqNativeScrollbarDescendants` to apply the same customization to the scrollbars of descendant elements.

**Example: Native scrollbar example** (`native-scrollbar`)

```ts native-scrollbar-example.ts
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { KbqNativeScrollbar } from '@koobiq/components/scrollbar';

@Component({
    selector: 'native-scrollbar-example',
    imports: [KbqNativeScrollbar],
    template: `
        <div kbqNativeScrollbar class="example-scrollbar">
            <p>
                In cryptography, a brute-force attack or exhaustive key search is a cryptanalytic attack that consists
                of an attacker submitting many possible keys or passwords with the hope of eventually guessing
                correctly. This strategy can theoretically be used to break any form of encryption that is not
                information-theoretically secure.[1] However, in a properly designed cryptosystem the chance of
                successfully guessing the key is negligible.
            </p>
            <p>
                When cracking passwords, this method is very fast when used to check all short passwords, but for longer
                passwords other methods such as the dictionary attack are used because a brute-force search takes too
                long. Longer passwords, passphrases and keys have more possible values, making them exponentially more
                difficult to crack than shorter ones due to the diversity of characters.[2]
            </p>
            <p>
                Brute-force attacks can be made less effective by implementing key stretching techniques making it more
                difficult for an attacker to recognize when the code has been cracked or by making the attacker do more
                work to test each guess. One of the measures of the strength of an encryption system is how long it
                would theoretically take an attacker to mount a successful brute-force attack against it.[3]
            </p>
        </div>
    `,
    styles: `
        :host {
            display: flex;
            flex-direction: column;
            align-items: center;
            padding: var(--kbq-size-l);
        }

        .example-scrollbar {
            overflow: auto;
            height: 200px;
            width: 100%;
            border-radius: var(--kbq-size-border-radius);
            background-color: var(--kbq-background-bg-secondary);
        }

        p {
            width: 150%;
            margin: var(--kbq-size-l);
        }
    `,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class NativeScrollbarExample {}
```

### Scroll events

Subscribe to `scrollChanges` to track `scroll` events:

```ts
import { afterNextRender, ChangeDetectionStrategy, Component, DestroyRef, inject, viewChild } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { KbqScrollbar } from '@koobiq/components/scrollbar';

@Component({
    imports: [KbqScrollbar],
    template: `
        <kbq-scrollbar>...</kbq-scrollbar>
    `,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class ScrollEventsExample {
    private readonly scrollbar = viewChild.required(KbqScrollbar);
    private readonly destroyRef = inject(DestroyRef);

    constructor() {
        afterNextRender(() => {
            this.scrollbar()
                .scrollChanges.pipe(takeUntilDestroyed(this.destroyRef))
                .subscribe(() => {
                    // Handle the scroll event.
                });
        });
    }
}
```

## API

### Components

#### KbqScrollbar (component)

Custom scrollbar wrapper: projects content and overlays a scrollbar track over it (created by its `KbqScrollbarViewport` host directive).

```ts
@Component({ selector: 'kbq-scrollbar', exportAs: 'kbqScrollbar' })
class KbqScrollbar {
    readonly mode = input<KbqScrollbarMode>(this.options.mode, {
        alias: 'kbqScrollbarMode'
    });
    readonly hideDelay = input<number>(this.options.hideDelay, {
        alias: 'kbqScrollbarHideDelay'
    });
    readonly scrollChanges: Observable<Event>;
    getNativeElement(): HTMLElement;
    scrollTo(options: KbqScrollbarScrollToOptions): void;
    scrollToTop(behavior?: ScrollBehavior): void;
    scrollToBottom(behavior?: ScrollBehavior): void;
    scrollStart(behavior?: ScrollBehavior): void;
    scrollEnd(behavior?: ScrollBehavior): void;
    scrollToElement(
        target: HTMLElement | string,
        options?: KbqScrollbarScrollToElementOptions
    ): void;
    scrollIntoView(
        target: HTMLElement,
        behavior?: ScrollBehavior
    ): void;
    flashScrollIndicators(): void;
}
```

- `[kbqScrollbarMode]`: `KbqScrollbarMode` — Visibility mode for the scrollbar. Defaults to the app-wide `KBQ_SCROLLBAR_OPTIONS`.
- `[kbqScrollbarHideDelay]`: `number` — How long the scroll-revealed `hover`-mode track stays visible after scrolling stops, in milliseconds.
  Defaults to the app-wide `KBQ_SCROLLBAR_OPTIONS`.
- `scrollChanges`: `Observable<Event>` — Emits on every native `scroll` event of the viewport. Emits outside Angular's zone — see `CdkScrollable.elementScrolled`.
- `getNativeElement()`: `HTMLElement` — The scrollbar's native scrollable element.
- `scrollTo()`: `void` — Scrolls to the specified offsets. RTL-normalized — see `CdkScrollable.scrollTo`.
- `scrollToTop()`: `void` — Scrolls to the start of the vertical axis.
- `scrollToBottom()`: `void` — Scrolls to the end of the vertical axis.
- `scrollStart()`: `void` — Scrolls to the logical start of the horizontal axis — the right edge in RTL, left in LTR.
- `scrollEnd()`: `void` — Scrolls to the logical end of the horizontal axis — the left edge in RTL, right in LTR.
- `scrollToElement()`: `void` — Scrolls `target` (an element, or a selector resolved against this scrollbar) into view.
- `scrollIntoView()`: `void` — Scrolls `target` to the center of the viewport.
- `flashScrollIndicators()`: `void` — Briefly reveals the scrollbar track — see `KbqScrollbarViewport.flashScrollIndicators`.

### Directives

#### KbqNativeScrollbar (directive)

Customizes the browser-rendered scrollbar of its host without replacing native scrolling.

```ts
@Directive({ selector: '[kbqNativeScrollbar]', exportAs: 'kbqNativeScrollbar' })
class KbqNativeScrollbar {
    readonly descendants = input<boolean>(this.options.descendants, {
        alias: 'kbqNativeScrollbarDescendants'
    });
}
```

- `[kbqNativeScrollbarDescendants]`: `boolean` — Whether browser-rendered scrollbars of descendant elements should also be customized.
  Defaults to `KBQ_NATIVE_SCROLLBAR_OPTIONS`.

#### KbqScrollbarViewport (directive)

Marks its host element as the custom scrollbar's scroll target, hiding its native scrollbar whenever a custom scrollbar track replaces it.

```ts
@Directive({ selector: '[kbqScrollbarViewport]' })
class KbqScrollbarViewport {
    readonly mode = input<KbqScrollbarMode>(this.options.mode, {
        alias: 'kbqScrollbarMode'
    });
    readonly hideDelay = input<number>(this.options.hideDelay, {
        alias: 'kbqScrollbarHideDelay'
    });
    readonly flashes: Observable<void>;
    readonly scrollChanges: Observable<Event>;
    flashScrollIndicators(): void;
    scrollTo(options: KbqScrollbarScrollToOptions): void;
    scrollToTop(behavior?: ScrollBehavior): void;
    scrollToBottom(behavior?: ScrollBehavior): void;
    scrollStart(behavior?: ScrollBehavior): void;
    scrollEnd(behavior?: ScrollBehavior): void;
    scrollToElement(
        target: HTMLElement | string,
        options?: KbqScrollbarScrollToElementOptions
    ): void;
    scrollIntoView(
        target: HTMLElement,
        behavior?: ScrollBehavior
    ): void;
    getNativeElement(): HTMLElement;
}
```

- `[kbqScrollbarMode]`: `KbqScrollbarMode` — Visibility mode for this viewport's scrollbar. Defaults to the app-wide `KBQ_SCROLLBAR_OPTIONS`.
- `[kbqScrollbarHideDelay]`: `number` — How long the scroll-revealed `hover`-mode track stays visible after scrolling stops, in milliseconds.
  Defaults to the app-wide `KBQ_SCROLLBAR_OPTIONS`.
- `flashes`: `Observable<void>` — Emits when `flashScrollIndicators` is called.
- `scrollChanges`: `Observable<Event>` — Emits on every native `scroll` event of the viewport. Emits outside Angular's zone — see `CdkScrollable.elementScrolled`.
- `flashScrollIndicators()`: `void` — Briefly reveals an overflowing `hover`-mode scrollbar.
- `scrollTo()`: `void` — Scrolls to the specified offsets. RTL-normalized — see `CdkScrollable.scrollTo`.
- `scrollToTop()`: `void` — Scrolls to the start of the vertical axis.
- `scrollToBottom()`: `void` — Scrolls to the end of the vertical axis.
- `scrollStart()`: `void` — Scrolls to the logical start of the horizontal axis — the right edge in RTL, left in LTR.
- `scrollEnd()`: `void` — Scrolls to the logical end of the horizontal axis — the left edge in RTL, right in LTR.
- `scrollToElement()`: `void` — Scrolls `target` (an element, or a selector resolved against this viewport) into view.
- `scrollIntoView()`: `void` — Scrolls `target` to the center of the viewport.
- `getNativeElement()`: `HTMLElement` — The viewport's native scrollable element — the host this directive is applied to.

### Functions

#### kbqNativeScrollbarOptionsProvider (function)

Overrides the default native scrollbar options within the given injector scope.

```ts
function kbqNativeScrollbarOptionsProvider(
    options: Partial<KbqNativeScrollbarOptions>
): Provider;
```

#### kbqScrollbarOptionsProvider (function)

Overrides the default scrollbar options within the given injector scope.

```ts
function kbqScrollbarOptionsProvider(
    options: Partial<KbqScrollbarOptions>
): Provider;
```

### Types

#### KbqNativeScrollbarOptions (type)

Configuration for `KbqNativeScrollbar`.

```ts
type KbqNativeScrollbarOptions = {
    descendants: boolean;
};
```

- `descendants`: `boolean` — Whether browser-rendered scrollbars of descendant elements should also be customized.

#### KbqScrollbarMode (type)

How the scrollbar is presented:
- `hover` — track appears on pointer hover or while scrolling (default);
- `always` — track is always visible while the content overflows;
- `native` — the browser's native scrollbar is used;
- `hidden` — no scrollbar is shown, but the content stays scrollable.

`hover` and `always` draw a bar only for an axis the user can scroll: one whose computed `overflow` is
`hidden`, `clip` or `visible` gets none, however far its content overflows.

```ts
type KbqScrollbarMode = 'always' | 'hidden' | 'hover' | 'native';
```

#### KbqScrollbarOptions (type)

Configuration for `KbqScrollbar`.

```ts
type KbqScrollbarOptions = {
    mode: KbqScrollbarMode;
    hideDelay: number;
};
```

- `hideDelay`: `number` — How long the scroll-revealed track stays visible after scrolling stops, in milliseconds.

#### KbqScrollbarScrollToElementOptions (type)

Options accepted by `KbqScrollbarViewport.scrollToElement`/`KbqScrollbar.scrollToElement`.

```ts
type KbqScrollbarScrollToElementOptions = {
    top?: number;
    left?: number;
    behavior?: ScrollBehavior;
};
```

- `top?`: `number` — Extra gap to leave above the target, in px — e.g. so it doesn't end up under a sticky header.
- `left?`: `number` — Extra gap to leave to the left of the target, in px.

#### KbqScrollbarScrollToOptions (type)

Options accepted by `KbqScrollbarViewport.scrollTo`/`KbqScrollbar.scrollTo` — RTL-normalized, see `CdkScrollable.scrollTo`.

```ts
type KbqScrollbarScrollToOptions = ExtendedScrollToOptions;
```

### Constants

#### KBQ_NATIVE_SCROLLBAR_OPTIONS (const)

Injection token holding the current `KbqNativeScrollbarOptions`.

```ts
const KBQ_NATIVE_SCROLLBAR_OPTIONS: InjectionToken<KbqNativeScrollbarOptions>;
```

#### KBQ_SCROLLBAR_OPTIONS (const)

Injection token holding the current `KbqScrollbarOptions`.

```ts
const KBQ_SCROLLBAR_OPTIONS: InjectionToken<KbqScrollbarOptions>;
```

## Examples

🚧 **Documentation in progress** 🚧

Unfortunately, the documentation for this section is not ready yet. We are actively working on its creation and plan to add it soon.

If you would like to contribute to the documentation or have any questions, please feel free to [open an issue](https://github.com/koobiq/angular-components/issues) in our GitHub repository.
