From 75358a81b7e9babb8c0a9fcb028b0423a1209b0f Mon Sep 17 00:00:00 2001 From: Alex Inkin Date: Mon, 2 Oct 2023 16:48:36 +0400 Subject: [PATCH] fix(core): `Dialog` fix scrollbar width issues (#5488) --- .cspell.json | 3 +- .../pull-to-refresh.component.ts | 2 +- .../pull-to-refresh.service.ts | 3 +- .../sheet/components/sheet/sheet.providers.ts | 2 +- .../sheet-stop/sheet-stop.directive.ts | 3 +- .../elastic-sticky/elastic-sticky.service.ts | 3 +- .../dialog-host/dialog-host.component.ts | 18 +- .../dialog-host/dialog-host.module.ts | 10 +- .../dialog-host/dialog-host.style.less | 26 ++- .../dialog-host/dialog-host.template.html | 6 +- projects/cdk/components/index.ts | 1 + .../cdk/components/scroll-controls/index.ts | 4 + .../scroll-controls/ng-package.json | 5 + .../scroll-controls.component.ts | 44 +++++ .../scroll-controls/scroll-controls.module.ts | 17 ++ .../scroll-controls.style.less | 87 +++++++++ .../scroll-controls.template.html | 22 +++ .../scroll-controls/scroll-ref.directive.ts | 15 ++ .../scroll-controls/scrollbar.directive.ts | 165 ++++++++++++++++++ projects/cdk/constants/parent-animation.ts | 7 +- .../auto-focus/handlers/default.handler.ts | 4 +- .../auto-focus/handlers/ios.handler.ts | 2 +- .../auto-focus/handlers/sync.handler.ts | 2 +- projects/cdk/tokens/dialogs.ts | 1 + projects/cdk/tokens/index.ts | 1 + projects/cdk/tokens/scroll-ref.ts | 10 ++ .../core/components/dialog/dialog.style.less | 3 +- projects/core/components/root/root.module.ts | 4 +- .../scroll-controls.component.ts | 4 +- .../scroll-controls/scroll-controls.module.ts | 1 + .../scroll-controls/scrollbar.directive.ts | 3 +- .../scrollbar/scroll-ref.directive.ts | 4 +- .../scrollbar/scrollbar.component.ts | 3 +- .../components/scrollbar/scrollbar.module.ts | 2 +- .../components/scrollbar/scrollbar.style.less | 4 + .../scrollbar/scrollbar.template.html | 5 +- projects/core/styles/mixins/mixins.less | 2 +- projects/core/styles/taiga-ui-theme.less | 1 - projects/core/styles/theme/dialog.less | 13 -- projects/core/tokens/scroll-ref.ts | 10 +- 40 files changed, 462 insertions(+), 60 deletions(-) create mode 100644 projects/cdk/components/scroll-controls/index.ts create mode 100644 projects/cdk/components/scroll-controls/ng-package.json create mode 100644 projects/cdk/components/scroll-controls/scroll-controls.component.ts create mode 100644 projects/cdk/components/scroll-controls/scroll-controls.module.ts create mode 100644 projects/cdk/components/scroll-controls/scroll-controls.style.less create mode 100644 projects/cdk/components/scroll-controls/scroll-controls.template.html create mode 100644 projects/cdk/components/scroll-controls/scroll-ref.directive.ts create mode 100644 projects/cdk/components/scroll-controls/scrollbar.directive.ts create mode 100644 projects/cdk/tokens/scroll-ref.ts delete mode 100644 projects/core/styles/theme/dialog.less diff --git a/.cspell.json b/.cspell.json index 2ad2e68d2a23..e0c82379389b 100644 --- a/.cspell.json +++ b/.cspell.json @@ -29,7 +29,8 @@ "letraset", "aldus", "hangoff", - "tcrm" + "tcrm", + "scrollbars" ], "ignoreRegExpList": ["\\(https?://.*?\\)", "\\/{1}.+\\/{1}", "\\%2F.+", "\\%2C.+", "\\ɵ.+", "\\ыва.+"], "overrides": [ diff --git a/projects/addon-mobile/components/pull-to-refresh/pull-to-refresh.component.ts b/projects/addon-mobile/components/pull-to-refresh/pull-to-refresh.component.ts index 64cd504be7a5..28ab85d64192 100644 --- a/projects/addon-mobile/components/pull-to-refresh/pull-to-refresh.component.ts +++ b/projects/addon-mobile/components/pull-to-refresh/pull-to-refresh.component.ts @@ -10,6 +10,7 @@ import { } from '@angular/core'; import { TUI_IS_IOS, + TUI_SCROLL_REF, TuiContextWithImplicit, TuiDestroyService, TuiHandler, @@ -17,7 +18,6 @@ import { tuiScrollFrom, tuiZonefree, } from '@taiga-ui/cdk'; -import {TUI_SCROLL_REF} from '@taiga-ui/core'; import {PolymorpheusContent} from '@tinkoff/ng-polymorpheus'; import {Observable} from 'rxjs'; import {distinctUntilChanged, filter, map, startWith, takeUntil} from 'rxjs/operators'; diff --git a/projects/addon-mobile/components/pull-to-refresh/pull-to-refresh.service.ts b/projects/addon-mobile/components/pull-to-refresh/pull-to-refresh.service.ts index de2a097b3aa8..ffa42f162797 100644 --- a/projects/addon-mobile/components/pull-to-refresh/pull-to-refresh.service.ts +++ b/projects/addon-mobile/components/pull-to-refresh/pull-to-refresh.service.ts @@ -1,6 +1,5 @@ import {ElementRef, Inject, Injectable} from '@angular/core'; -import {tuiScrollFrom, tuiTypedFromEvent} from '@taiga-ui/cdk'; -import {TUI_SCROLL_REF} from '@taiga-ui/core'; +import {TUI_SCROLL_REF, tuiScrollFrom, tuiTypedFromEvent} from '@taiga-ui/cdk'; import {EMPTY, Observable} from 'rxjs'; import { distinctUntilChanged, diff --git a/projects/addon-mobile/components/sheet/components/sheet/sheet.providers.ts b/projects/addon-mobile/components/sheet/components/sheet/sheet.providers.ts index af6c4b0af888..4ee02a81d727 100644 --- a/projects/addon-mobile/components/sheet/components/sheet/sheet.providers.ts +++ b/projects/addon-mobile/components/sheet/components/sheet/sheet.providers.ts @@ -4,10 +4,10 @@ import { ALWAYS_FALSE_HANDLER, ALWAYS_TRUE_HANDLER, TUI_IS_IOS, + TUI_SCROLL_REF, tuiTypedFromEvent, tuiZonefree, } from '@taiga-ui/cdk'; -import {TUI_SCROLL_REF} from '@taiga-ui/core'; import {merge, Observable} from 'rxjs'; import {map, share} from 'rxjs/operators'; diff --git a/projects/addon-mobile/components/sheet/directives/sheet-stop/sheet-stop.directive.ts b/projects/addon-mobile/components/sheet/directives/sheet-stop/sheet-stop.directive.ts index f371ae8fd997..67f7432505a8 100644 --- a/projects/addon-mobile/components/sheet/directives/sheet-stop/sheet-stop.directive.ts +++ b/projects/addon-mobile/components/sheet/directives/sheet-stop/sheet-stop.directive.ts @@ -1,6 +1,5 @@ import {Directive, ElementRef, Inject, Self} from '@angular/core'; -import {TuiDestroyService} from '@taiga-ui/cdk'; -import {TUI_SCROLL_REF} from '@taiga-ui/core'; +import {TUI_SCROLL_REF, TuiDestroyService} from '@taiga-ui/cdk'; import {Observable} from 'rxjs'; import { distinctUntilChanged, diff --git a/projects/addon-mobile/directives/elastic-sticky/elastic-sticky.service.ts b/projects/addon-mobile/directives/elastic-sticky/elastic-sticky.service.ts index 31154234e811..cb54ec86d200 100644 --- a/projects/addon-mobile/directives/elastic-sticky/elastic-sticky.service.ts +++ b/projects/addon-mobile/directives/elastic-sticky/elastic-sticky.service.ts @@ -1,11 +1,12 @@ import {ElementRef, Inject, Injectable, NgZone, Self} from '@angular/core'; import { + SCROLL_REF_SELECTOR, + TUI_SCROLL_REF, TuiDestroyService, tuiGetElementOffset, tuiScrollFrom, tuiZoneOptimized, } from '@taiga-ui/cdk'; -import {SCROLL_REF_SELECTOR, TUI_SCROLL_REF} from '@taiga-ui/core'; import {Observable} from 'rxjs'; import { distinctUntilChanged, diff --git a/projects/cdk/components/dialog-host/dialog-host.component.ts b/projects/cdk/components/dialog-host/dialog-host.component.ts index 9074e9dff427..ca7b26cc125d 100644 --- a/projects/cdk/components/dialog-host/dialog-host.component.ts +++ b/projects/cdk/components/dialog-host/dialog-host.component.ts @@ -1,3 +1,4 @@ +import {animateChild, query, style, transition, trigger} from '@angular/animations'; import {DOCUMENT} from '@angular/common'; import { ChangeDetectionStrategy, @@ -9,9 +10,8 @@ import { } from '@angular/core'; import {Title} from '@angular/platform-browser'; import {HISTORY} from '@ng-web-apis/common'; -import {TUI_PARENT_ANIMATION} from '@taiga-ui/cdk/constants'; import {TuiDestroyService} from '@taiga-ui/cdk/services'; -import {TUI_DIALOGS} from '@taiga-ui/cdk/tokens'; +import {TUI_DIALOGS, TUI_IS_MOBILE} from '@taiga-ui/cdk/tokens'; import {TuiDialog} from '@taiga-ui/cdk/types'; import {tuiCreateToken} from '@taiga-ui/cdk/utils'; import {combineLatest, Observable, of} from 'rxjs'; @@ -36,7 +36,18 @@ const isFakeHistoryState = ( // eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection changeDetection: ChangeDetectionStrategy.Default, providers: [TuiDestroyService], - animations: [TUI_PARENT_ANIMATION], + animations: [ + trigger('host', [ + transition(':enter', [ + style({overflow: 'clip'}), + query(':scope > *', [animateChild()], {optional: true}), + ]), + transition(':leave', [ + style({overflow: 'clip'}), + query(':scope > *', [animateChild()], {optional: true}), + ]), + ]), + ], }) export class TuiDialogHostComponent> implements OnInit @@ -44,6 +55,7 @@ export class TuiDialogHostComponent> dialogs: readonly T[] = []; constructor( + @Inject(TUI_IS_MOBILE) readonly isMobile: boolean, @Inject(TUI_DIALOG_CLOSES_ON_BACK) readonly isDialogClosesOnBack$: Observable, @Inject(TUI_DIALOGS) diff --git a/projects/cdk/components/dialog-host/dialog-host.module.ts b/projects/cdk/components/dialog-host/dialog-host.module.ts index 2e4639bee66b..5b0236ab5704 100644 --- a/projects/cdk/components/dialog-host/dialog-host.module.ts +++ b/projects/cdk/components/dialog-host/dialog-host.module.ts @@ -1,8 +1,11 @@ import {CommonModule} from '@angular/common'; import {NgModule} from '@angular/core'; -import {TuiLetModule} from '@taiga-ui/cdk/directives'; -import {TuiFocusTrapModule} from '@taiga-ui/cdk/directives/focus-trap'; -import {TuiOverscrollModule} from '@taiga-ui/cdk/directives/overscroll'; +import {TuiScrollControlsModule} from '@taiga-ui/cdk/components/scroll-controls'; +import { + TuiFocusTrapModule, + TuiLetModule, + TuiOverscrollModule, +} from '@taiga-ui/cdk/directives'; import {PolymorpheusModule} from '@tinkoff/ng-polymorpheus'; import {TuiDialogHostComponent} from './dialog-host.component'; @@ -14,6 +17,7 @@ import {TuiDialogHostComponent} from './dialog-host.component'; TuiOverscrollModule, TuiFocusTrapModule, TuiLetModule, + TuiScrollControlsModule, ], declarations: [TuiDialogHostComponent], exports: [TuiDialogHostComponent], diff --git a/projects/cdk/components/dialog-host/dialog-host.style.less b/projects/cdk/components/dialog-host/dialog-host.style.less index 7399b39e1717..6f60bbb22cad 100644 --- a/projects/cdk/components/dialog-host/dialog-host.style.less +++ b/projects/cdk/components/dialog-host/dialog-host.style.less @@ -17,8 +17,18 @@ align-items: flex-start; outline: none; overflow: auto; - //noinspection CssInvalidPropertyValue - overflow: overlay; + + /* stylelint-disable*/ + scrollbar-width: none; + -ms-overflow-style: none; + /* stylelint-enable*/ + + &::-webkit-scrollbar, + &::-webkit-scrollbar-thumb { + background: transparent; + width: 0; + height: 0; + } } .t-dialog { @@ -35,7 +45,7 @@ /* change of useless property 'letter-spacing' to ensure that transitionend event will fire */ transition: - opacity var(--tui-duration), + opacity var(--tui-duration, 300ms), letter-spacing 0.01s; background: rgba(0, 0, 0, 0.75); backdrop-filter: var(--tui-backdrop, none); @@ -49,3 +59,13 @@ .t-dialog:last-of-type { z-index: 1; } + +.t-scrollbars { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + margin: 0; + color: #747474; +} diff --git a/projects/cdk/components/dialog-host/dialog-host.template.html b/projects/cdk/components/dialog-host/dialog-host.template.html index 1ceba163a78a..131f3ea7a430 100644 --- a/projects/cdk/components/dialog-host/dialog-host.template.html +++ b/projects/cdk/components/dialog-host/dialog-host.template.html @@ -6,10 +6,14 @@ tuiOverscroll="all" tuiScrollRef class="t-dialog" - @tuiParentAnimation + @host [attr.aria-labelledby]="item.id" > +
this.scrollbars), + startWith([false, false]), + distinctUntilChanged((a, b) => a[0] === b[0] && a[1] === b[1]), + tuiZoneOptimized(this.zone), + ); + + constructor( + @Inject(NgZone) private readonly zone: NgZone, + @Inject(TUI_SCROLL_REF) private readonly scrollRef: ElementRef, + @Inject(ANIMATION_FRAME) private readonly animationFrame$: Observable, + ) {} + + private get scrollbars(): [boolean, boolean] { + const {clientHeight, scrollHeight, clientWidth, scrollWidth} = + this.scrollRef.nativeElement; + + return [ + Math.ceil((clientHeight / scrollHeight) * 100) < 100, + Math.ceil((clientWidth / scrollWidth) * 100) < 100, + ]; + } +} diff --git a/projects/cdk/components/scroll-controls/scroll-controls.module.ts b/projects/cdk/components/scroll-controls/scroll-controls.module.ts new file mode 100644 index 000000000000..bb6725b23c67 --- /dev/null +++ b/projects/cdk/components/scroll-controls/scroll-controls.module.ts @@ -0,0 +1,17 @@ +import {CommonModule} from '@angular/common'; +import {NgModule} from '@angular/core'; + +import {TuiScrollControlsComponent} from './scroll-controls.component'; +import {TuiScrollRefDirective} from './scroll-ref.directive'; +import {TuiScrollbarDirective} from './scrollbar.directive'; + +@NgModule({ + imports: [CommonModule], + declarations: [ + TuiScrollbarDirective, + TuiScrollControlsComponent, + TuiScrollRefDirective, + ], + exports: [TuiScrollControlsComponent, TuiScrollRefDirective], +}) +export class TuiScrollControlsModule {} diff --git a/projects/cdk/components/scroll-controls/scroll-controls.style.less b/projects/cdk/components/scroll-controls/scroll-controls.style.less new file mode 100644 index 000000000000..6103ba65b855 --- /dev/null +++ b/projects/cdk/components/scroll-controls/scroll-controls.style.less @@ -0,0 +1,87 @@ +@scroll-width: 0.75rem; +@scroll-width-large: 0.875rem; +@scroll-min-size: 1.25rem; + +:host { + position: sticky; + top: 0; + left: 0; + z-index: 1; + min-width: calc(100% - 1px); + min-height: calc(100% - 1px); + max-width: calc(100% - 1px); + max-height: calc(100% - 1px); + float: left; + margin-inline-end: calc(-100% + 1px); + pointer-events: none; +} + +.t-bar { + position: absolute; + right: 0; + bottom: 0; + pointer-events: auto; + animation: tuiFadeIn var(--tui-duration, 300ms) ease-in-out; + + &_vertical { + top: 0; + width: @scroll-width-large; + } + + &_horizontal { + left: 0; + height: @scroll-width-large; + } + + &_has-horizontal { + bottom: @scroll-width - 0.25rem; + } + + &_has-vertical { + right: @scroll-width - 0.25rem; + } +} + +.t-thumb { + position: absolute; + border-radius: 6.25rem; + border: 0.25rem solid transparent; + cursor: pointer; + pointer-events: auto; + background: currentColor; + background-clip: content-box; + box-sizing: border-box; + transition: all var(--tui-duration, 300ms) ease-in-out; + transition-property: width, height, opacity; + opacity: 0.2; + + &:hover { + opacity: 0.24; + } + + &:active { + opacity: 0.48; + } + + .t-bar_vertical & { + right: 0; + width: @scroll-width; + min-height: @scroll-min-size; + } + + .t-bar_vertical:hover &, + .t-bar_vertical &:active { + width: @scroll-width-large; + } + + .t-bar_horizontal & { + bottom: 0; + height: @scroll-width; + min-width: @scroll-min-size; + } + + .t-bar_horizontal:hover &, + .t-bar_horizontal &:active { + height: @scroll-width-large; + } +} diff --git a/projects/cdk/components/scroll-controls/scroll-controls.template.html b/projects/cdk/components/scroll-controls/scroll-controls.template.html new file mode 100644 index 000000000000..33c08437c4f1 --- /dev/null +++ b/projects/cdk/components/scroll-controls/scroll-controls.template.html @@ -0,0 +1,22 @@ + +
+
+
+
+
+
+
diff --git a/projects/cdk/components/scroll-controls/scroll-ref.directive.ts b/projects/cdk/components/scroll-controls/scroll-ref.directive.ts new file mode 100644 index 000000000000..1aa21d55f83e --- /dev/null +++ b/projects/cdk/components/scroll-controls/scroll-ref.directive.ts @@ -0,0 +1,15 @@ +import {Directive, ElementRef} from '@angular/core'; +import {TUI_SCROLL_REF} from '@taiga-ui/cdk/tokens'; + +export const SCROLL_REF_SELECTOR = '[tuiScrollRef]'; + +@Directive({ + selector: SCROLL_REF_SELECTOR, + providers: [ + { + provide: TUI_SCROLL_REF, + useExisting: ElementRef, + }, + ], +}) +export class TuiScrollRefDirective {} diff --git a/projects/cdk/components/scroll-controls/scrollbar.directive.ts b/projects/cdk/components/scroll-controls/scrollbar.directive.ts new file mode 100644 index 000000000000..1121082bdc96 --- /dev/null +++ b/projects/cdk/components/scroll-controls/scrollbar.directive.ts @@ -0,0 +1,165 @@ +import {DOCUMENT} from '@angular/common'; +import {Directive, ElementRef, Inject, Input, NgZone, Self} from '@angular/core'; +import {ANIMATION_FRAME} from '@ng-web-apis/common'; +import {POLLING_TIME} from '@taiga-ui/cdk/constants'; +import { + tuiPreventDefault, + tuiScrollFrom, + tuiStopPropagation, + tuiTypedFromEvent, + tuiZonefree, +} from '@taiga-ui/cdk/observables'; +import {TuiDestroyService} from '@taiga-ui/cdk/services'; +import {TUI_SCROLL_REF} from '@taiga-ui/cdk/tokens'; +import {merge, Observable} from 'rxjs'; +import {map, switchMap, takeUntil, throttleTime} from 'rxjs/operators'; + +const MIN_WIDTH = 24; + +@Directive({ + selector: '[tuiScrollbar]', + providers: [TuiDestroyService], +}) +export class TuiScrollbarDirective { + @Input() + tuiScrollbar: 'horizontal' | 'vertical' = 'vertical'; + + constructor( + @Inject(NgZone) zone: NgZone, + @Self() @Inject(TuiDestroyService) destroy$: Observable, + @Inject(ANIMATION_FRAME) animationFrame$: Observable, + @Inject(TUI_SCROLL_REF) private readonly container: ElementRef, + @Inject(DOCUMENT) private readonly doc: Document, + @Inject(ElementRef) private readonly el: ElementRef, + ) { + const {nativeElement} = this.el; + const mousedown$ = tuiTypedFromEvent(nativeElement, 'mousedown'); + const mousemove$ = tuiTypedFromEvent(this.doc, 'mousemove'); + const mouseup$ = tuiTypedFromEvent(this.doc, 'mouseup'); + const mousedownWrapper$ = tuiTypedFromEvent(this.wrapper, 'mousedown'); + + merge( + mousedownWrapper$.pipe( + tuiPreventDefault(), + map(event => this.getScrolled(event, 0.5, 0.5)), + ), + mousedown$.pipe( + tuiPreventDefault(), + tuiStopPropagation(), + switchMap(event => { + const rect = nativeElement.getBoundingClientRect(); + const vertical = getOffsetVertical(event, rect); + const horizontal = getOffsetHorizontal(event, rect); + + return mousemove$.pipe( + map(event => this.getScrolled(event, vertical, horizontal)), + takeUntil(mouseup$), + ); + }), + ), + ) + .pipe(tuiZonefree(zone), takeUntil(destroy$)) + .subscribe(([scrollTop, scrollLeft]) => { + if (this.tuiScrollbar === 'vertical') { + this.element.scrollTop = scrollTop; + } else { + this.element.scrollLeft = scrollLeft; + } + }); + + merge( + animationFrame$.pipe(throttleTime(POLLING_TIME)), + tuiScrollFrom(this.element), + ) + .pipe(tuiZonefree(zone), takeUntil(destroy$)) + .subscribe(() => { + if (this.tuiScrollbar === 'vertical') { + nativeElement.style.top = `${this.thumb * 100}%`; + nativeElement.style.height = `${this.view * 100}%`; + } else { + nativeElement.style.left = `${this.thumb * 100}%`; + nativeElement.style.width = `${this.view * 100}%`; + } + }); + } + + private get wrapper(): Element { + return this.el.nativeElement.parentElement!; + } + + private get scrolled(): number { + const { + scrollTop, + scrollHeight, + clientHeight, + scrollLeft, + scrollWidth, + clientWidth, + } = this.element; + + return this.tuiScrollbar === 'vertical' + ? scrollTop / (scrollHeight - clientHeight) + : scrollLeft / (scrollWidth - clientWidth); + } + + private get compensation(): number { + const {clientHeight, scrollHeight, clientWidth, scrollWidth} = this.element; + + if ( + ((clientHeight * clientHeight) / scrollHeight > MIN_WIDTH && + this.tuiScrollbar === 'vertical') || + ((clientWidth * clientWidth) / scrollWidth > MIN_WIDTH && + this.tuiScrollbar === 'horizontal') + ) { + return 0; + } + + return this.tuiScrollbar === 'vertical' + ? MIN_WIDTH / clientHeight + : MIN_WIDTH / clientWidth; + } + + private get thumb(): number { + const compensation = this.compensation || this.view; + + return this.scrolled * (1 - compensation); + } + + private get view(): number { + const {clientHeight, scrollHeight, clientWidth, scrollWidth} = this.element; + + return this.tuiScrollbar === 'vertical' + ? Math.ceil((clientHeight / scrollHeight) * 100) / 100 + : Math.ceil((clientWidth / scrollWidth) * 100) / 100; + } + + private get element(): Element { + return this.container.nativeElement; + } + + private getScrolled( + {clientY, clientX}: MouseEvent, + offsetVertical: number, + offsetHorizontal: number, + ): [number, number] { + const {offsetHeight, offsetWidth} = this.el.nativeElement; + const {top, left, width, height} = this.wrapper.getBoundingClientRect(); + + const maxTop = this.element.scrollHeight - height; + const maxLeft = this.element.scrollWidth - width; + const scrolledTop = + (clientY - top - offsetHeight * offsetVertical) / (height - offsetHeight); + const scrolledLeft = + (clientX - left - offsetWidth * offsetHorizontal) / (width - offsetWidth); + + return [maxTop * scrolledTop, maxLeft * scrolledLeft]; + } +} + +function getOffsetVertical({clientY}: MouseEvent, {top, height}: ClientRect): number { + return (clientY - top) / height; +} + +function getOffsetHorizontal({clientX}: MouseEvent, {left, width}: ClientRect): number { + return (clientX - left) / width; +} diff --git a/projects/cdk/constants/parent-animation.ts b/projects/cdk/constants/parent-animation.ts index eb2cc275ffa1..8149be19ff50 100644 --- a/projects/cdk/constants/parent-animation.ts +++ b/projects/cdk/constants/parent-animation.ts @@ -1,13 +1,10 @@ -import {animateChild, query, style, transition, trigger} from '@angular/animations'; +import {animateChild, query, transition, trigger} from '@angular/animations'; /** * Add to enable child :leave animation (fixes https://github.com/angular/angular/issues/15753) */ export const TUI_PARENT_ANIMATION = trigger(`tuiParentAnimation`, [ - transition(`* => void`, [ - style({overflow: `hidden`}), - query(`:scope > *`, [animateChild()], {optional: true}), - ]), + transition(`:leave`, [query(`:scope > *`, [animateChild()], {optional: true})]), ]); /** diff --git a/projects/cdk/directives/auto-focus/handlers/default.handler.ts b/projects/cdk/directives/auto-focus/handlers/default.handler.ts index f3a936d5954b..ea38b06f9a20 100644 --- a/projects/cdk/directives/auto-focus/handlers/default.handler.ts +++ b/projects/cdk/directives/auto-focus/handlers/default.handler.ts @@ -34,9 +34,9 @@ export class TuiDefaultAutofocusHandler extends AbstractTuiAutofocusHandler { skipWhile(Boolean), take(1), ), - ).subscribe(() => this.element.focus()); + ).subscribe(() => this.element.focus({preventScroll: true})); } else { - this.element.focus(); + this.element.focus({preventScroll: true}); } } } diff --git a/projects/cdk/directives/auto-focus/handlers/ios.handler.ts b/projects/cdk/directives/auto-focus/handlers/ios.handler.ts index 978a4fec40b8..acda1db542cd 100644 --- a/projects/cdk/directives/auto-focus/handlers/ios.handler.ts +++ b/projects/cdk/directives/auto-focus/handlers/ios.handler.ts @@ -47,7 +47,7 @@ export class TuiIosAutofocusHandler extends AbstractTuiAutofocusHandler { if (this.isTextFieldElement) { this.zone.runOutsideAngular(() => this.iosWebkitAutofocus()); } else { - this.element.focus(); + this.element.focus({preventScroll: true}); } } diff --git a/projects/cdk/directives/auto-focus/handlers/sync.handler.ts b/projects/cdk/directives/auto-focus/handlers/sync.handler.ts index 49ed96ac6510..d4062f0fa91c 100644 --- a/projects/cdk/directives/auto-focus/handlers/sync.handler.ts +++ b/projects/cdk/directives/auto-focus/handlers/sync.handler.ts @@ -17,6 +17,6 @@ export class TuiSynchronousAutofocusHandler extends AbstractTuiAutofocusHandler } setFocus(): void { - this.element.focus(); + this.element.focus({preventScroll: true}); } } diff --git a/projects/cdk/tokens/dialogs.ts b/projects/cdk/tokens/dialogs.ts index 66775bc65340..a61a507b78f8 100644 --- a/projects/cdk/tokens/dialogs.ts +++ b/projects/cdk/tokens/dialogs.ts @@ -10,6 +10,7 @@ export const TUI_DIALOGS = tuiCreateToken< ReadonlyArray> >([]); +// TODO: Refactor dialogs in 4.0 so there is no need for module imports export function tuiAsDialog( useExisting: Type>, ): Provider { diff --git a/projects/cdk/tokens/index.ts b/projects/cdk/tokens/index.ts index 687f1433e649..5d9d234b5d34 100644 --- a/projects/cdk/tokens/index.ts +++ b/projects/cdk/tokens/index.ts @@ -20,6 +20,7 @@ export * from './is-webkit'; export * from './platform'; export * from './range'; export * from './removed-element'; +export * from './scroll-ref'; export * from './swipe-options'; export * from './take-only-trusted-events'; export * from './touch-supported'; diff --git a/projects/cdk/tokens/scroll-ref.ts b/projects/cdk/tokens/scroll-ref.ts new file mode 100644 index 000000000000..0c017a2fe044 --- /dev/null +++ b/projects/cdk/tokens/scroll-ref.ts @@ -0,0 +1,10 @@ +import {DOCUMENT} from '@angular/common'; +import {ElementRef, inject} from '@angular/core'; +import {tuiCreateTokenFromFactory} from '@taiga-ui/cdk/utils'; + +/** + * Scrollable container + */ +export const TUI_SCROLL_REF = tuiCreateTokenFromFactory( + () => new ElementRef(inject(DOCUMENT).documentElement), +); diff --git a/projects/core/components/dialog/dialog.style.less b/projects/core/components/dialog/dialog.style.less index 7e700fdff622..c76ab49916c9 100644 --- a/projects/core/components/dialog/dialog.style.less +++ b/projects/core/components/dialog/dialog.style.less @@ -54,7 +54,8 @@ &[data-size='fullscreen'], &[data-size='page'] { - width: 100%; + /* stylelint-disable-next-line */ + min-width: 100vw; min-height: 100%; border-radius: 0; border: none; diff --git a/projects/core/components/root/root.module.ts b/projects/core/components/root/root.module.ts index 5af88e97b5c0..fc616a599d2c 100644 --- a/projects/core/components/root/root.module.ts +++ b/projects/core/components/root/root.module.ts @@ -3,11 +3,10 @@ import {NgModule} from '@angular/core'; import { TuiAlertHostModule, TuiDialogHostModule, - TuiDragModule, TuiDropdownHostModule, + TuiScrollControlsModule, } from '@taiga-ui/cdk'; import {TuiHintsHostModule} from '@taiga-ui/core/components/hints-host'; -import {TuiScrollControlsModule} from '@taiga-ui/core/components/scroll-controls'; import {TuiSvgDefsHostModule} from '@taiga-ui/core/internal/svg-defs-host'; import {EventPluginsModule} from '@tinkoff/ng-event-plugins'; @@ -17,7 +16,6 @@ import {TuiRootComponent} from './root.component'; imports: [ CommonModule, EventPluginsModule, - TuiDragModule, TuiDropdownHostModule, TuiSvgDefsHostModule, TuiHintsHostModule, diff --git a/projects/core/components/scroll-controls/scroll-controls.component.ts b/projects/core/components/scroll-controls/scroll-controls.component.ts index c3efde9b0c02..a359cb4d6f70 100644 --- a/projects/core/components/scroll-controls/scroll-controls.component.ts +++ b/projects/core/components/scroll-controls/scroll-controls.component.ts @@ -7,10 +7,10 @@ import { NgZone, } from '@angular/core'; import {ANIMATION_FRAME} from '@ng-web-apis/common'; -import {tuiZoneOptimized} from '@taiga-ui/cdk'; +import {TUI_SCROLL_REF, tuiZoneOptimized} from '@taiga-ui/cdk'; import {tuiFadeIn} from '@taiga-ui/core/animations'; import {MODE_PROVIDER} from '@taiga-ui/core/providers'; -import {TUI_ANIMATION_OPTIONS, TUI_MODE, TUI_SCROLL_REF} from '@taiga-ui/core/tokens'; +import {TUI_ANIMATION_OPTIONS, TUI_MODE} from '@taiga-ui/core/tokens'; import {TuiBrightness} from '@taiga-ui/core/types'; import {Observable} from 'rxjs'; import {distinctUntilChanged, map, startWith, throttleTime} from 'rxjs/operators'; diff --git a/projects/core/components/scroll-controls/scroll-controls.module.ts b/projects/core/components/scroll-controls/scroll-controls.module.ts index f77b872279e2..0dcd3164e092 100644 --- a/projects/core/components/scroll-controls/scroll-controls.module.ts +++ b/projects/core/components/scroll-controls/scroll-controls.module.ts @@ -6,6 +6,7 @@ import {TuiScrollControlsComponent} from './scroll-controls.component'; import {TuiScrollbarDirective} from './scrollbar.directive'; import {TuiScrollbarWrapperDirective} from './scrollbar-wrapper.directive'; +/** @deprecated import from `@taiga-ui/cdk` instead */ @NgModule({ imports: [CommonModule, TuiLetModule], declarations: [ diff --git a/projects/core/components/scroll-controls/scrollbar.directive.ts b/projects/core/components/scroll-controls/scrollbar.directive.ts index 1f83a28763be..86f2dccda9af 100644 --- a/projects/core/components/scroll-controls/scrollbar.directive.ts +++ b/projects/core/components/scroll-controls/scrollbar.directive.ts @@ -11,6 +11,7 @@ import { import {ANIMATION_FRAME} from '@ng-web-apis/common'; import { POLLING_TIME, + TUI_SCROLL_REF, TuiDestroyService, tuiPreventDefault, tuiScrollFrom, @@ -18,7 +19,7 @@ import { tuiTypedFromEvent, tuiZonefree, } from '@taiga-ui/cdk'; -import {TUI_ELEMENT_REF, TUI_SCROLL_REF} from '@taiga-ui/core/tokens'; +import {TUI_ELEMENT_REF} from '@taiga-ui/core/tokens'; import {TuiOrientation} from '@taiga-ui/core/types'; import {merge, Observable} from 'rxjs'; import {map, switchMap, takeUntil, throttleTime} from 'rxjs/operators'; diff --git a/projects/core/components/scrollbar/scroll-ref.directive.ts b/projects/core/components/scrollbar/scroll-ref.directive.ts index 530703825b0e..c2757c5ffd1a 100644 --- a/projects/core/components/scrollbar/scroll-ref.directive.ts +++ b/projects/core/components/scrollbar/scroll-ref.directive.ts @@ -1,8 +1,10 @@ import {Directive, ElementRef} from '@angular/core'; -import {TUI_SCROLL_REF} from '@taiga-ui/core/tokens'; +import {TUI_SCROLL_REF} from '@taiga-ui/cdk'; +/** @deprecated import from `@taiga-ui/cdk` instead */ export const SCROLL_REF_SELECTOR = '[tuiScrollRef]'; +/** @deprecated import from `@taiga-ui/cdk` instead */ @Directive({ selector: SCROLL_REF_SELECTOR, providers: [ diff --git a/projects/core/components/scrollbar/scrollbar.component.ts b/projects/core/components/scrollbar/scrollbar.component.ts index 3aeea7150c9a..1dd8bedc74c6 100644 --- a/projects/core/components/scrollbar/scrollbar.component.ts +++ b/projects/core/components/scrollbar/scrollbar.component.ts @@ -10,13 +10,14 @@ import { import {CSS as CSS_TOKEN, USER_AGENT} from '@ng-web-apis/common'; import { TUI_IS_IOS, + TUI_SCROLL_REF, tuiGetElementOffset, TuiInjectionTokenType, tuiIsFirefox, } from '@taiga-ui/cdk'; import {TUI_SCROLL_INTO_VIEW, TUI_SCROLLABLE} from '@taiga-ui/core/constants'; -import {TUI_SCROLL_REF} from '@taiga-ui/core/tokens'; +// TODO: Remove all legacy code in 4.0 @Component({ selector: 'tui-scrollbar', templateUrl: './scrollbar.template.html', diff --git a/projects/core/components/scrollbar/scrollbar.module.ts b/projects/core/components/scrollbar/scrollbar.module.ts index cdead12a3f3b..4ea24c1ddb53 100644 --- a/projects/core/components/scrollbar/scrollbar.module.ts +++ b/projects/core/components/scrollbar/scrollbar.module.ts @@ -1,6 +1,6 @@ import {CommonModule} from '@angular/common'; import {NgModule} from '@angular/core'; -import {TuiScrollControlsModule} from '@taiga-ui/core/components/scroll-controls'; +import {TuiScrollControlsModule} from '@taiga-ui/cdk'; import {TuiScrollRefDirective} from './scroll-ref.directive'; import {TuiScrollableDirective} from './scrollable.directive'; diff --git a/projects/core/components/scrollbar/scrollbar.style.less b/projects/core/components/scrollbar/scrollbar.style.less index c3c4d1aa94d7..f91ac203c6c3 100644 --- a/projects/core/components/scrollbar/scrollbar.style.less +++ b/projects/core/components/scrollbar/scrollbar.style.less @@ -33,3 +33,7 @@ width: 100%; height: max-content; } + +.t-bars { + color: var(--tui-text-01); +} diff --git a/projects/core/components/scrollbar/scrollbar.template.html b/projects/core/components/scrollbar/scrollbar.template.html index 9fa8ccd2bb8d..fe01c7e4c943 100644 --- a/projects/core/components/scrollbar/scrollbar.template.html +++ b/projects/core/components/scrollbar/scrollbar.template.html @@ -1,4 +1,7 @@ - +
diff --git a/projects/core/styles/mixins/mixins.less b/projects/core/styles/mixins/mixins.less index ce67f1e975c6..6dbdca088cae 100644 --- a/projects/core/styles/mixins/mixins.less +++ b/projects/core/styles/mixins/mixins.less @@ -133,7 +133,7 @@ height: 1rem; border-radius: 6.25rem; background-clip: padding-box; - border: 2.667rem solid transparent; + border: 0.375rem solid transparent; } &::-webkit-scrollbar { diff --git a/projects/core/styles/taiga-ui-theme.less b/projects/core/styles/taiga-ui-theme.less index 9ad25fb60954..04b9d1806640 100644 --- a/projects/core/styles/taiga-ui-theme.less +++ b/projects/core/styles/taiga-ui-theme.less @@ -1,4 +1,3 @@ -@import 'theme/dialog.less'; @import 'theme/variables.less'; @import 'theme/wrapper.less'; @import 'theme/calendar.less'; diff --git a/projects/core/styles/theme/dialog.less b/projects/core/styles/theme/dialog.less deleted file mode 100644 index 7f359ea1e4a6..000000000000 --- a/projects/core/styles/theme/dialog.less +++ /dev/null @@ -1,13 +0,0 @@ -@import '../mixins/mixins.less'; - -tui-root:not(._mobile) tui-dialog-host > section { - .customize-scroll(); - - &::-webkit-scrollbar-thumb { - background-color: rgba(168, 168, 168, 0.5); - - &:hover { - background-color: rgba(204, 204, 204, 0.5); - } - } -} diff --git a/projects/core/tokens/scroll-ref.ts b/projects/core/tokens/scroll-ref.ts index 097688c6bd71..e1b10093e364 100644 --- a/projects/core/tokens/scroll-ref.ts +++ b/projects/core/tokens/scroll-ref.ts @@ -1,10 +1,6 @@ -import {DOCUMENT} from '@angular/common'; -import {ElementRef, inject} from '@angular/core'; -import {tuiCreateTokenFromFactory} from '@taiga-ui/cdk'; +import {TUI_SCROLL_REF as TOKEN} from '@taiga-ui/cdk'; /** - * Scrollable container + * @deprecated import from `@taiga-ui/cdk` instead */ -export const TUI_SCROLL_REF = tuiCreateTokenFromFactory( - () => new ElementRef(inject(DOCUMENT).documentElement), -); +export const TUI_SCROLL_REF = TOKEN;