1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-06 00:13:28 +00:00

[SG-286] Allow vault filter to be scrollable (#2687)

* Switch to programmatic CdkOverlay instead of directive

* lint && prettier
This commit is contained in:
Robyn MacCallum
2022-05-16 12:32:19 -04:00
committed by GitHub
parent fae7fd9378
commit 076b0cbf1f
3 changed files with 71 additions and 21 deletions

View File

@@ -112,12 +112,14 @@ app-root > div {
}
main::-webkit-scrollbar,
cdk-virtual-scroll-viewport::-webkit-scrollbar {
cdk-virtual-scroll-viewport::-webkit-scrollbar,
.vault-select::-webkit-scrollbar {
width: 10px;
height: 10px;
}
main::-webkit-scrollbar-track {
main::-webkit-scrollbar-track,
.vault-select::-webkit-scrollbar-track {
background-color: transparent;
}
@@ -128,7 +130,8 @@ cdk-virtual-scroll-viewport::-webkit-scrollbar-track {
}
main::-webkit-scrollbar-thumb,
cdk-virtual-scroll-viewport::-webkit-scrollbar-thumb {
cdk-virtual-scroll-viewport::-webkit-scrollbar-thumb,
.vault-select::-webkit-scrollbar-thumb {
border-radius: 10px;
margin-right: 1px;
@@ -483,6 +486,10 @@ main {
}
}
.vault-select {
overflow-y: auto;
display: flex;
flex-direction: column;
@include themify($themes) {
background-color: themed("boxBackgroundColor");
}

View File

@@ -1,9 +1,8 @@
<div class="content org-filter-content" *ngIf="loaded && show">
<button
#toggleVaults
class="org-filter"
(click)="toggle()"
cdkOverlayOrigin
#trigger="cdkOverlayOrigin"
(click)="openOverlay()"
aria-haspopup="menu"
aria-controls="cdk-overlay-container"
[attr.aria-expanded]="isOpen"
@@ -16,16 +15,7 @@
[ngClass]="{ 'bwi-angle-down': !isOpen, 'bwi-chevron-up': isOpen }"
></i>
</button>
<ng-template
cdkConnectedOverlay
[cdkConnectedOverlayOrigin]="trigger"
[cdkConnectedOverlayHasBackdrop]="true"
[cdkConnectedOverlayBackdropClass]="'cdk-overlay-transparent-backdrop'"
[cdkConnectedOverlayOpen]="isOpen"
[cdkConnectedOverlayPositions]="overlayPostition"
(backdropClick)="close()"
(detach)="close()"
>
<ng-template class="vault-select-container" #vaultSelectorTemplate>
<div
class="vault-select"
[@transformPanel]="'open'"

View File

@@ -1,6 +1,18 @@
import { animate, state, style, transition, trigger } from "@angular/animations";
import { ConnectedPosition } from "@angular/cdk/overlay";
import { Component, EventEmitter, NgZone, OnInit, Output } from "@angular/core";
import { ConnectedPosition, Overlay, OverlayRef } from "@angular/cdk/overlay";
import { TemplatePortal } from "@angular/cdk/portal";
import {
Component,
ElementRef,
EventEmitter,
NgZone,
OnInit,
Output,
TemplateRef,
ViewChild,
ViewContainerRef,
} from "@angular/core";
import { merge } from "rxjs";
import { VaultFilter } from "jslib-angular/modules/vault-filter/models/vault-filter.model";
import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service";
@@ -36,6 +48,10 @@ import { VaultFilterService } from "../../services/vaultFilter.service";
export class VaultSelectComponent implements OnInit {
@Output() onVaultSelectionChanged = new EventEmitter();
@ViewChild("toggleVaults", { read: ElementRef })
buttonRef: ElementRef<HTMLButtonElement>;
@ViewChild("vaultSelectorTemplate", { read: TemplateRef }) templateRef: TemplateRef<HTMLElement>;
isOpen = false;
loaded = false;
organizations: Organization[];
@@ -51,6 +67,8 @@ export class VaultSelectComponent implements OnInit {
},
];
private overlayRef: OverlayRef;
get show() {
return (
(this.organizations.length > 0 && !this.enforcePersonalOwnwership) ||
@@ -62,7 +80,9 @@ export class VaultSelectComponent implements OnInit {
private vaultFilterService: VaultFilterService,
private i18nService: I18nService,
private ngZone: NgZone,
private broadcasterService: BroadcasterService
private broadcasterService: BroadcasterService,
private overlay: Overlay,
private viewContainerRef: ViewContainerRef
) {}
async ngOnInit() {
@@ -108,11 +128,44 @@ export class VaultSelectComponent implements OnInit {
this.loaded = true;
}
toggle() {
this.isOpen = !this.isOpen;
openOverlay() {
const viewPortHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
const positionStrategyBuilder = this.overlay.position();
const positionStrategy = positionStrategyBuilder
.flexibleConnectedTo(this.buttonRef.nativeElement)
.withFlexibleDimensions(true)
.withPush(true)
.withViewportMargin(10)
.withGrowAfterOpen(true)
.withPositions(this.overlayPostition);
this.overlayRef = this.overlay.create({
hasBackdrop: false,
positionStrategy,
maxHeight: viewPortHeight - 160,
backdropClass: "cdk-overlay-transparent-backdrop",
});
const templatePortal = new TemplatePortal(this.templateRef, this.viewContainerRef);
this.overlayRef.attach(templatePortal);
this.isOpen = true;
// Handle closing
merge(
this.overlayRef.outsidePointerEvents(),
this.overlayRef.backdropClick(),
this.overlayRef.detachments()
).subscribe(() => {
this.close();
});
}
close() {
if (this.overlayRef) {
this.overlayRef.dispose();
this.overlayRef = undefined;
}
this.isOpen = false;
}