Skip to content

Commit

Permalink
feat(core): support using native scrollbar
Browse files Browse the repository at this point in the history
  • Loading branch information
splincode committed Oct 4, 2024
1 parent 84ec7ae commit 3efe63b
Show file tree
Hide file tree
Showing 19 changed files with 170 additions and 55 deletions.
32 changes: 22 additions & 10 deletions projects/core/components/root/root.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ import {tuiWatch, tuiZonefreeScheduler} from '@taiga-ui/cdk/observables';
import {TUI_IS_MOBILE} from '@taiga-ui/cdk/tokens';
import {TuiAlerts} from '@taiga-ui/core/components/alert';
import {TUI_DIALOGS, TuiDialogs} from '@taiga-ui/core/components/dialog';
import {TuiScrollControls} from '@taiga-ui/core/components/scrollbar';
import {
TUI_SCROLLBAR_OPTIONS,
TuiScrollControls,
} from '@taiga-ui/core/components/scrollbar';
import {TuiDropdowns} from '@taiga-ui/core/directives';
import {TuiHints} from '@taiga-ui/core/directives/hint';
import {TuiBreakpointService} from '@taiga-ui/core/services';
Expand Down Expand Up @@ -57,22 +60,31 @@ export class TuiRoot {
{initialValue: false},
);

protected readonly scrollbars = inject(TUI_IS_MOBILE)
? signal(false)
: toSignal(
inject<Observable<readonly unknown[]>>(TUI_DIALOGS).pipe(
map(({length}) => !length),
debounceTime(0, tuiZonefreeScheduler()),
),
{initialValue: false},
);
protected readonly nativeScrollbar = inject(TUI_SCROLLBAR_OPTIONS).nativeScrollbar;

protected readonly scrollbars =
this.nativeScrollbar || inject(TUI_IS_MOBILE)
? signal(false)
: toSignal(
inject<Observable<readonly unknown[]>>(TUI_DIALOGS).pipe(
map(({length}) => !length),
debounceTime(0, tuiZonefreeScheduler()),
),
{initialValue: false},
);

constructor() {
inject(DOCUMENT).documentElement.setAttribute(
'data-tui-theme',
inject(TUI_THEME).toLowerCase(),
);

if (!this.nativeScrollbar) {
inject(DOCUMENT).defaultView?.document.documentElement.classList.add(
'tui-zero-scrollbar',
);
}

ngDevMode &&
console.assert(
!!inject<unknown[]>(EVENT_MANAGER_PLUGINS).find(
Expand Down
1 change: 0 additions & 1 deletion projects/core/components/root/root.style.less
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
}
}

html[data-tui-theme],
.tui-zero-scrollbar {
.scrollbar-hidden();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {tuiToAnimationOptions} from '@taiga-ui/core/utils';
import {distinctUntilChanged, map, startWith, throttleTime} from 'rxjs';

import {TuiScrollbarDirective} from './scrollbar.directive';
import {TUI_SCROLLBAR_OPTIONS} from './scrollbar.options';

@Component({
standalone: true,
Expand All @@ -21,7 +22,11 @@ import {TuiScrollbarDirective} from './scrollbar.directive';
export class TuiScrollControls {
private readonly scrollRef = inject(TUI_SCROLL_REF).nativeElement;

protected readonly options = tuiToAnimationOptions(inject(TUI_ANIMATIONS_SPEED));
protected readonly options = inject(TUI_SCROLLBAR_OPTIONS);
protected readonly animationOptions = tuiToAnimationOptions(
inject(TUI_ANIMATIONS_SPEED),
);

protected readonly refresh$ = inject(WA_ANIMATION_FRAME).pipe(
throttleTime(300, tuiZonefreeScheduler()),
map(() => this.scrollbars),
Expand Down
51 changes: 27 additions & 24 deletions projects/core/components/scrollbar/scroll-controls.template.html
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
<ng-container *ngIf="refresh$ | async as bars">
<div
*ngIf="bars[0]"
class="t-bar t-bar_vertical"
[@tuiFadeIn]="options"
[class.t-bar_has-horizontal]="bars[1]"
(mousedown.capture.prevent)="(0)"
>
<ng-container *ngIf="options.nativeScrollbar; else custom" />
<ng-template #custom>
<ng-container *ngIf="refresh$ | async as bars">
<div
tuiScrollbar="vertical"
class="t-thumb"
></div>
</div>
<div
*ngIf="bars[1]"
class="t-bar t-bar_horizontal"
[@tuiFadeIn]="options"
[class.t-bar_has-vertical]="bars[0]"
(mousedown.capture.prevent)="(0)"
>
*ngIf="bars[0]"
class="t-bar t-bar_vertical"
[@tuiFadeIn]="animationOptions"
[class.t-bar_has-horizontal]="bars[1]"
(mousedown.capture.prevent)="(0)"
>
<div
tuiScrollbar="vertical"
class="t-thumb"
></div>
</div>
<div
tuiScrollbar="horizontal"
class="t-thumb"
></div>
</div>
</ng-container>
*ngIf="bars[1]"
class="t-bar t-bar_horizontal"
[@tuiFadeIn]="animationOptions"
[class.t-bar_has-vertical]="bars[0]"
(mousedown.capture.prevent)="(0)"
>
<div
tuiScrollbar="horizontal"
class="t-thumb"
></div>
</div>
</ng-container>
</ng-template>
4 changes: 2 additions & 2 deletions projects/core/components/scrollbar/scrollbar.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const TUI_SCROLLABLE = 'tui-scrollable';
},
],
host: {
'[class._native-hidden]': '!isIOS || hidden',
'[class._native-hidden]': '!options.nativeScrollbar && (!isIOS || hidden)',
[`(${TUI_SCROLLABLE}.stop)`]: 'scrollRef = $event.detail',
[`(${TUI_SCROLL_INTO_VIEW}.stop)`]: 'scrollIntoView($event.detail)',
},
Expand All @@ -54,7 +54,7 @@ export class TuiScrollbar {
public hidden = false;

protected get delegated(): boolean {
return this.scrollRef !== this.el;
return this.scrollRef !== this.el || this.options.nativeScrollbar;
}

protected get scrollRef(): HTMLElement {
Expand Down
2 changes: 2 additions & 0 deletions projects/core/components/scrollbar/scrollbar.options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import type {Provider} from '@angular/core';
import {tuiCreateToken, tuiProvideOptions} from '@taiga-ui/cdk/utils/miscellaneous';

export interface TuiScrollbarOptions {
nativeScrollbar: boolean;
mode: 'always' | 'hover';
}

export const TUI_DEFAULT_SCROLLBAR_OPTIONS: TuiScrollbarOptions = {
nativeScrollbar: false,
mode: 'always',
};

Expand Down
2 changes: 1 addition & 1 deletion projects/core/components/scrollbar/scrollbar.template.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<tui-scroll-controls
*ngIf="!hidden && !isIOS"
*ngIf="!hidden && !isIOS && !options.nativeScrollbar"
class="t-bars"
[class.t-hover-mode]="options.mode === 'hover'"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
appendOnly
itemSize="50"
tuiScrollable
class="tui-zero-scrollbar"
[class.tui-zero-scrollbar]="!nativeScrollbar"
>
<div *cdkVirtualFor="let user of users; templateCacheSize: 0">
<tui-line-clamp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ import {
CdkVirtualForOf,
CdkVirtualScrollViewport,
} from '@angular/cdk/scrolling';
import {NgIf} from '@angular/common';
import {Component} from '@angular/core';
import {Component, inject} from '@angular/core';
import {changeDetection} from '@demo/emulate/change-detection';
import {encapsulation} from '@demo/emulate/encapsulation';
import {TuiScrollable, TuiScrollbar} from '@taiga-ui/core';
import {TUI_SCROLLBAR_OPTIONS, TuiScrollable, TuiScrollbar} from '@taiga-ui/core';
import {TuiLineClamp} from '@taiga-ui/kit';

@Component({
Expand All @@ -16,7 +15,6 @@ import {TuiLineClamp} from '@taiga-ui/kit';
CdkFixedSizeVirtualScroll,
CdkVirtualForOf,
CdkVirtualScrollViewport,
NgIf,
TuiLineClamp,
TuiScrollable,
TuiScrollbar,
Expand Down Expand Up @@ -202,6 +200,8 @@ export default class Example {
'Paradox',
];

protected readonly nativeScrollbar = inject(TUI_SCROLLBAR_OPTIONS).nativeScrollbar;

protected readonly users = Array.from(new Array(10_000), (_, index) => {
const firstName = this.names[Math.floor(Math.random() * this.names.length)] ?? '';
const lastName =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
appendOnly
itemSize="50"
tuiScrollable
class="example-viewport tui-zero-scrollbar"
class="example-viewport"
[class.tui-zero-scrollbar]="!nativeScrollbar"
>
<div
*cdkVirtualFor="let item of items"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
CdkVirtualForOf,
CdkVirtualScrollViewport,
} from '@angular/cdk/scrolling';
import {NgForOf} from '@angular/common';
import {Component, inject} from '@angular/core';
import {changeDetection} from '@demo/emulate/change-detection';
import {encapsulation} from '@demo/emulate/encapsulation';
Expand All @@ -14,7 +13,12 @@ import {
TuiPullToRefresh,
} from '@taiga-ui/addon-mobile';
import {TUI_IS_ANDROID, TUI_IS_IOS} from '@taiga-ui/cdk';
import {TuiAlertService, TuiButton, TuiScrollable, TuiScrollbar} from '@taiga-ui/core';
import {
TUI_SCROLLBAR_OPTIONS,
TuiAlertService,
TuiScrollable,
TuiScrollbar,
} from '@taiga-ui/core';
import {Subject} from 'rxjs';

@Component({
Expand All @@ -23,8 +27,6 @@ import {Subject} from 'rxjs';
CdkFixedSizeVirtualScroll,
CdkVirtualForOf,
CdkVirtualScrollViewport,
NgForOf,
TuiButton,
TuiPullToRefresh,
TuiScrollable,
TuiScrollbar,
Expand Down Expand Up @@ -55,6 +57,8 @@ import {Subject} from 'rxjs';
export default class Example {
private readonly alerts = inject(TuiAlertService);

protected readonly nativeScrollbar = inject(TUI_SCROLLBAR_OPTIONS).nativeScrollbar;

protected items = Array.from({length: 10000}).map((_, i) => `Item #${i}`);

protected onPull(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
appendOnly
itemSize="50"
tuiScrollable
class="example-viewport tui-zero-scrollbar"
class="example-viewport"
[class.tui-zero-scrollbar]="!nativeScrollbar"
>
<div
*cdkVirtualFor="let item of items"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import {
CdkVirtualForOf,
CdkVirtualScrollViewport,
} from '@angular/cdk/scrolling';
import {Component} from '@angular/core';
import {Component, inject} from '@angular/core';
import {changeDetection} from '@demo/emulate/change-detection';
import {encapsulation} from '@demo/emulate/encapsulation';
import {TuiScrollable, TuiScrollbar} from '@taiga-ui/core';
import {TUI_SCROLLBAR_OPTIONS, TuiScrollable, TuiScrollbar} from '@taiga-ui/core';

@Component({
standalone: true,
Expand All @@ -23,6 +23,8 @@ import {TuiScrollable, TuiScrollbar} from '@taiga-ui/core';
changeDetection,
})
export default class Example {
protected readonly nativeScrollbar = inject(TUI_SCROLLBAR_OPTIONS).nativeScrollbar;

protected items = Array.from({length: 10000}).map((_, i) => `Item #${i}`);

protected add(): void {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<tui-scrollbar class="box">
<div class="content">
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deleniti dignissimos, doloremque. Aperiam
assumenda atque aut blanditiis corporis, eum, facilis harum laudantium magni necessitatibus nobis quas
repudiandae sint ut voluptatem! Optio.
</p>
<p>
Accusamus aperiam assumenda aut consectetur, corporis delectus, dolor eaque eius est hic impedit labore
possimus provident quas rem, rerum sequi sint tempora tempore ut? Debitis esse neque odio odit provident?
</p>
<p>
Cum eum illo, ipsa iure nostrum ut voluptates? Autem blanditiis corporis debitis deserunt ex expedita
facilis fuga, illum iusto magnam praesentium provident recusandae repudiandae, totam, voluptatem. Minima
numquam sapiente sunt.
</p>
<p>
Beatae consectetur cupiditate dignissimos ducimus eos excepturi labore pariatur placeat quia similique.
Architecto aspernatur cumque debitis distinctio esse, facere fugit harum ipsum libero minus neque numquam
omnis quidem, tempora, ut!
</p>
<p>
Mollitia, perspiciatis sunt! Architecto aspernatur assumenda beatae, blanditiis commodi consequuntur debitis
et id, laboriosam maxime molestiae neque nihil officiis omnis, quam quos sint veritatis voluptate? Alias
deserunt distinctio modi perferendis?
</p>
<p>
Ab aspernatur aut cumque cupiditate deleniti, dolorem ducimus eligendi eos facere harum hic ipsam ipsum iste
itaque modi nam necessitatibus nostrum nulla omnis quae repellat, sapiente sit tempore. Ipsam, quidem!
</p>
<p>
Ab debitis deleniti distinctio est ex facere magni nemo numquam placeat quia, quibusdam sequi! Aliquid at
consectetur culpa ea enim facilis, harum hic, inventore iste possimus praesentium quas tempora voluptates.
</p>
<p>
Aliquam eligendi ipsam modi nemo numquam obcaecati officia, quidem unde? Accusantium amet, animi deleniti
dolorum ea earum eos, expedita ipsa minima modi, pariatur perspiciatis porro quibusdam quo repellat tempore
voluptates!
</p>
<p>
Ab assumenda fugiat magni natus officiis perferendis ratione rem repellendus tenetur. At commodi laudantium
modi, natus nobis nulla odio odit sed sint tempora tenetur voluptas? At odio praesentium quas ut!
</p>
<p>
Atque aut consectetur consequuntur debitis eius facere ipsa ipsam maiores minima minus mollitia qui quos
repudiandae sapiente, soluta? Ad, amet dolore doloribus ducimus eos exercitationem molestiae quisquam soluta
ullam voluptate.
</p>
</div>
</tui-scrollbar>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.box {
inline-size: 16rem;
block-size: 16rem;
border: 1px solid;
}

.content {
padding: 0 0.6875rem;
}

p {
white-space: nowrap;
}
19 changes: 19 additions & 0 deletions projects/demo/src/modules/components/scrollbar/examples/8/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {Component} from '@angular/core';
import {changeDetection} from '@demo/emulate/change-detection';
import {encapsulation} from '@demo/emulate/encapsulation';
import {TuiScrollbar, tuiScrollbarOptionsProvider} from '@taiga-ui/core';

@Component({
standalone: true,
imports: [TuiScrollbar],
templateUrl: './index.html',
styleUrls: ['./index.less'],
encapsulation,
changeDetection,
providers: [
tuiScrollbarOptionsProvider({
nativeScrollbar: true,
}),
],
})
export default class Example {}
1 change: 1 addition & 0 deletions projects/demo/src/modules/components/scrollbar/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ export default class Page {
'Light scrollbar',
'Virtual scroll',
'Show scroll bars on hover',
'Native scrollbar',
];
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
#viewport
appendOnly
tuiScrollable
class="viewport tui-zero-scrollbar"
class="viewport"
[class.tui-zero-scrollbar]="!nativeScrollbar"
[itemSize]="45"
[maxBufferPx]="500"
[minBufferPx]="400"
Expand Down
Loading

0 comments on commit 3efe63b

Please sign in to comment.