mirror of
https://github.com/bitwarden/browser
synced 2025-12-18 01:03:35 +00:00
[CL-834] Use intersection observer to determine if content scrolls (#16099)
* use intersection observer to fix dynamic content load issue * set up mock intersection observer * Create reusable hasScrollable content util * return null from resize to fix type error * remove Observer mock * return observable * refactor util and remove resize * use async pipe for observable in template * remove comment left in error
This commit is contained in:
@@ -65,9 +65,10 @@
|
||||
}"
|
||||
>
|
||||
<ng-content select="[bitDialogContent]"></ng-content>
|
||||
<div #scrollBottom></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@let isScrollable = isScrollable$ | async;
|
||||
@let showFooterBorder =
|
||||
(!bodyHasScrolledFrom().top && isScrollable) || bodyHasScrolledFrom().bottom;
|
||||
<footer
|
||||
|
||||
@@ -8,13 +8,17 @@ import {
|
||||
viewChild,
|
||||
input,
|
||||
booleanAttribute,
|
||||
AfterViewInit,
|
||||
ElementRef,
|
||||
DestroyRef,
|
||||
} from "@angular/core";
|
||||
import { toObservable } from "@angular/core/rxjs-interop";
|
||||
import { combineLatest, switchMap } from "rxjs";
|
||||
|
||||
import { I18nPipe } from "@bitwarden/ui-common";
|
||||
|
||||
import { BitIconButtonComponent } from "../../icon-button/icon-button.component";
|
||||
import { TypographyDirective } from "../../typography/typography.directive";
|
||||
import { hasScrollableContent$ } from "../../utils/";
|
||||
import { hasScrolledFrom } from "../../utils/has-scrolled-from";
|
||||
import { fadeIn } from "../animations";
|
||||
import { DialogRef } from "../dialog.service";
|
||||
@@ -39,11 +43,22 @@ import { DialogTitleContainerDirective } from "../directives/dialog-title-contai
|
||||
CdkScrollable,
|
||||
],
|
||||
})
|
||||
export class DialogComponent implements AfterViewInit {
|
||||
protected dialogRef = inject(DialogRef, { optional: true });
|
||||
export class DialogComponent {
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
private scrollableBody = viewChild.required(CdkScrollable);
|
||||
private scrollBottom = viewChild.required<ElementRef<HTMLDivElement>>("scrollBottom");
|
||||
|
||||
protected dialogRef = inject(DialogRef, { optional: true });
|
||||
protected bodyHasScrolledFrom = hasScrolledFrom(this.scrollableBody);
|
||||
protected isScrollable = false;
|
||||
|
||||
private scrollableBody$ = toObservable(this.scrollableBody);
|
||||
private scrollBottom$ = toObservable(this.scrollBottom);
|
||||
|
||||
protected isScrollable$ = combineLatest([this.scrollableBody$, this.scrollBottom$]).pipe(
|
||||
switchMap(([body, bottom]) =>
|
||||
hasScrollableContent$(body.getElementRef().nativeElement, bottom.nativeElement),
|
||||
),
|
||||
);
|
||||
|
||||
/** Background color */
|
||||
readonly background = input<"default" | "alt">("default");
|
||||
@@ -105,13 +120,4 @@ export class DialogComponent implements AfterViewInit {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.isScrollable = this.canScroll();
|
||||
}
|
||||
|
||||
canScroll(): boolean {
|
||||
const el = this.scrollableBody().getElementRef().nativeElement as HTMLElement;
|
||||
return el.scrollHeight > el.clientHeight;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user